我仅使用两个线程进行了一次小型测试,如下所示:
print(f'Number {x:02x}')
有时候,输出将仅包括其中之一,在我开始介绍import static java.lang.System.out;
@Test
public void testTwoSimpleThreads() {
doInParallelAsync(() -> {
out.println("First Ok");
},
() -> {
out.println("Second Ok");
});
}
private void doInParallelAsync(Runnable first, Runnable second) {
new Thread(() -> {
first.run();
}).start();
new Thread(() -> {
second.run();
}).start();
}
之后,它们会开始。
到目前为止,我遇到了两个不同的输出:
join()
First Ok
我知道First Ok
Second Ok
是同步的,而且我知道 main 线程创建的线程默认是用户线程,而用户线程不会退出,直到完成。
尽管我使用的是 @Test ,但我测试了它们是否像预期的那样是非守护进程。
是守护程序线程,当且仅当创建线程是守护程序时
还有
Java虚拟机将继续执行线程,直到发生以下任何一种情况为止:
已调用Runtime类的退出方法,并且安全管理器已允许进行退出操作。
不是守护程序线程的所有线程都已死亡,或者是从调用返回到run方法,或者是抛出了传播到run方法之外的异常。
< / li>
实际上,我知道答案指出什么,不知道为什么输出消失了?
我需要问的问题:
管道被主线程关闭了吗?
为什么?是否因为每个管道独立地绑定到一个线程?不分享? (该管道直到最后一个线程像引用计数一样被关闭-在没有人使用它之前,不会删除该文件)
管道似乎已被我提到的println()
关闭。谢谢@meriton指出来。
当我在普通 @Test
中尝试此方法并直接在main()
之后直接调用System.exit(0);
时,输出与该输出完全相同使用start()
时。
使用@Test
(Junit)时,将不等待线程。有关更多详细信息,请检查JUnit test not executing all threads created within the test和JUnit terminates child threads。
这是@Alex Lockwood的解释,我个人更喜欢:
JUnit是一个单元测试框架...与Android框架一样,它具有一个主线程,从中可以调用用户定义的单元测试方法。当单元测试返回时,JUnit立即调用下一个单元测试方法(如果没有更多要调用的单元测试方法,则JUnit完全退出)。 JUnit对您创建/启动的后台线程一无所知,因此您不能假设它会停滞不前并等待它们完成。
答案 0 :(得分:2)
那是因为您是在不同的线程上启动它们的,而main thread
不必等待child threads
完成,而是将在最后一行之后立即关闭其执行。
因此,到那时,如果执行了线程1,输出将是:
First Ok
如果执行了线程2:
Second Ok
如果运气好的话都被执行了,那么
First Ok
Second Ok
或
Second Ok
First Ok
通过提供join
,您是在要求main thread
等待child thread
完成并因此等待两个输出。
-编辑-
这并不意味着子线程已终止,它们仍然完成了执行,但由于此时可能已关闭或释放了外流,因此您可能看不到结果
如果在Jshell上执行相同的命令,则始终会得到第二个输出,但是有时它会作为另一个命令进入,因为一旦主线程完成,Jshell就会移至下一个命令行:
答案 1 :(得分:2)
在所有测试运行之后,测试运行程序是否可以调用System.exit()
?如果将测试转换为普通的main()
方法,可以重现部分输出吗?
(我会尝试一下,但在Eclipse中作为JUnit测试运行时无法重现部分输出)
...而且不,System.out
是一个静态字段,因此被所有线程共享。退出主线程不会关闭流。