线程似乎没有干净地退出 - 线程挂起
Thread doesn't seem to exit cleanly - thread hang
所以我尝试根据我对 Java 内存模型 (JMM) 的了解进行一些测试,因为我想看看它们如何应用于 try-catch 块中的初始化+赋值抛出一个异常,我得到了我想要的结果(不相关,但我想知道在 try-catch 中分配是否可以在初始化之前发生,然后在抛出一些异常之前,其他线程是否可以看到抛出异常之前未初始化的对象 - 答案似乎是否定的),但是我遇到了一些与我的线程相关的奇怪问题 运行.
基本上,我的线程似乎永远不会退出。我 运行 我的代码在调试器中完成,我可以看到两个线程 运行。我的主线程是 Thread,而线程是我创建的 Thread-1。在我完成 main 方法后,我的主线程消失了,如预期的那样被 DestroyJavaVM 取代。但是,Thread-1 似乎在等待什么。
真正让我困惑的部分,除了代码太简单以至于搞砸之外,是如果我把一个
System.out.print("");
在 while 块内部,然后由 I/O 引起的减速似乎导致线程在它正在做的任何事情上都 "catch-up",并看到中断。我注意到的另一件事是,如果我在 "finished" #println() 语句上放置一个断点,线程将在该行中断,并允许我继续,这会导致标准输出中的打印语句,程序退出。这对我来说没有多大意义。幕后发生了什么导致创建的线程看不到中断?
这是我的测试代码,删除了与我测试 JMM 相关的不重要位:
public class Foo{
static Foo p;
public static void main(String [] args){
Thread t = new Thread(new Runnable(){
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
}
System.out.println("finished");
}
});
t.start();
for(int i = 0; i < 100000; i++){
try{
p = new Foo();
}catch(Exception pse){
}
}
t.interrupt();
System.out.println("main-method-completed");
}
}
只要线程运行其 while 循环,它就不会从系统中的其他线程获取任何消息。例如,如果您这样做,Thread.sleep(1);
线程将暂停,并且会发生上下文切换到其他内容。当线程恢复时,它会得到一些主循环线程的中断通知。
如果你想停止线程中的循环,你可以使用一个 volatile
变量(这些变量是从共享内存中明确写入和读取的,并且非常昂贵),或者使用,例如,一个 java.util.conncurrent.atomic.AtomicBoolean
,至少在理论上可以使用一些更便宜的方法在线程之间传递其状态。
您可能已经重现了错误 JDK-6772683 : Thread.isInterrupted() fails to return true on multiprocessor PC。
所以我尝试根据我对 Java 内存模型 (JMM) 的了解进行一些测试,因为我想看看它们如何应用于 try-catch 块中的初始化+赋值抛出一个异常,我得到了我想要的结果(不相关,但我想知道在 try-catch 中分配是否可以在初始化之前发生,然后在抛出一些异常之前,其他线程是否可以看到抛出异常之前未初始化的对象 - 答案似乎是否定的),但是我遇到了一些与我的线程相关的奇怪问题 运行.
基本上,我的线程似乎永远不会退出。我 运行 我的代码在调试器中完成,我可以看到两个线程 运行。我的主线程是 Thread,而线程是我创建的 Thread-1。在我完成 main 方法后,我的主线程消失了,如预期的那样被 DestroyJavaVM 取代。但是,Thread-1 似乎在等待什么。
真正让我困惑的部分,除了代码太简单以至于搞砸之外,是如果我把一个
System.out.print("");
在 while 块内部,然后由 I/O 引起的减速似乎导致线程在它正在做的任何事情上都 "catch-up",并看到中断。我注意到的另一件事是,如果我在 "finished" #println() 语句上放置一个断点,线程将在该行中断,并允许我继续,这会导致标准输出中的打印语句,程序退出。这对我来说没有多大意义。幕后发生了什么导致创建的线程看不到中断?
这是我的测试代码,删除了与我测试 JMM 相关的不重要位:
public class Foo{
static Foo p;
public static void main(String [] args){
Thread t = new Thread(new Runnable(){
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
}
System.out.println("finished");
}
});
t.start();
for(int i = 0; i < 100000; i++){
try{
p = new Foo();
}catch(Exception pse){
}
}
t.interrupt();
System.out.println("main-method-completed");
}
}
只要线程运行其 while 循环,它就不会从系统中的其他线程获取任何消息。例如,如果您这样做,Thread.sleep(1);
线程将暂停,并且会发生上下文切换到其他内容。当线程恢复时,它会得到一些主循环线程的中断通知。
如果你想停止线程中的循环,你可以使用一个 volatile
变量(这些变量是从共享内存中明确写入和读取的,并且非常昂贵),或者使用,例如,一个 java.util.conncurrent.atomic.AtomicBoolean
,至少在理论上可以使用一些更便宜的方法在线程之间传递其状态。
您可能已经重现了错误 JDK-6772683 : Thread.isInterrupted() fails to return true on multiprocessor PC。