好的,我问了 this 个问题作为 Android 问题,但我意识到我能够在纯 Java 应用程序上重新创建类似的场景。
我创建了一个 Thread 类作为内部类并覆盖它的 run() 方法
Thread aaa = new Thread(){
public void run() {
for(int i=0;i<5;i++){
System.out.println(getId()+" <-"+i);
try {
Thread.sleep(1000 * 1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
};
在我的 Main 方法中,我启动了该线程,然后休眠了 6 秒(这个想法是线程会在 main 醒来之前完成它的运行方法)然后我再次尝试启动同一个线程
public static void main(String[] args) {
Test test = new Test();
//Start the thread
test.aaa.start();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Start same dead thread again
test.aaa.start();
}
在我的 Ubuntu 机器上,在最后一行中再次启动线程给出了 IllegalThreadStateException,这是我认为的规范。输出看起来像:
9 <-0
9 <-1
9 <-2
9 <-3
9 <-4
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at Test.main(Test.java:15)
但是在我的 Android 设备上,它再次运行相同的线程,输出看起来像:
50023 <-0
50023 <-1
50023 <-2
50023 <-3
50023 <-4
50023 <-0
50023 <-1
50023 <-2
50023 <-3
50023 <-4
我不明白同一个线程是如何再次启动的,至少 Id 证明了这一点。
答案 0 :(得分:2)
我认为造成您困惑的原因是您正在两个相似但不相同的运行时环境中进行测试。换句话说,这里有两种不同的运行时环境或虚拟机(又名 VM)在起作用:
您描述的第二次调用 thread.start()
导致 IllegalThreadStateException
的行为是基于 JVM 的标准 Java 运行时环境中的正确行为。
您遇到的代码不会在您的设备上崩溃的行为是因为您的 Android 设备上的 Java 运行时环境不同 -- 它不完全符合 JVM spec。
答案 1 :(得分:1)
根据 Java 规范,您只能启动一个线程一次。换句话说,你不能启动一个已经启动的线程。
它恰好适用于 Android(或其他任何地方)这一事实无关紧要。即使它看起来有效,它仍然是错误的,并且可能导致不可预测的结果。
如果您需要再次运行一个线程,请创建一个新线程。
作为替代方案,您可以使用 ExecutorService
,但这是一个不同的主题。