【发布时间】:2018-06-27 01:18:04
【问题描述】:
我有一个只使用 两个线程 的小测试,如下所示:
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
我知道println() 是同步的,而且我知道 main 线程创建的线程默认是用户线程,用户线程不会退出 直到他们完成。
虽然我使用的是 @Test,但我测试了它们是 非守护进程,正如预期的那样。
当且仅当创建线程是守护线程时才是守护线程
和
Java 虚拟机继续执行线程,直到发生以下任一情况:
已调用 Runtime 类的退出方法,并且安全管理器已允许进行退出操作。
所有不是守护线程的线程都已经死亡,要么是从对 run 方法的调用返回,要么是抛出一个传播到 run 方法之外的异常。
更新
其实我知道答案指出了什么,不知道为什么输出消失了?
我需要问的问题:
-
主线程关闭的管道?
-
为什么?是因为每个管道都独立地绑定到一个线程吗?不共享? (在最后一个线程完成之前管道不会关闭,就像 引用计数 - 文件不会被删除,直到没有人使用它)
-
最后一个问题:它是由JVM控制还是依赖于操作系统?
管道似乎被我提到的@Test 关闭了。谢谢@meriton 指出。
结论
当我在普通main()中尝试此方法时,直接在start()之后调用System.exit(0);,输出与使用@Test时的输出完全相同。
当使用@Test (Junit) 时,线程不会被等待。更多详情请查看JUnit test not executing all threads created within the test和JUnit terminates child threads。
这是我个人更喜欢的@Alex Lockwood 的解释:
JUnit 是一个单元测试框架...与 Android 框架一样,它有一个主线程,从中可以调用用户定义的单元测试方法。当单元测试返回时,JUnit 立即调用下一个单元测试方法(如果没有更多单元测试方法可以调用,则完全退出)。 JUnit 对您创建/启动的后台线程一无所知,因此您不能假设它会坐在那里等待它们完成。
【问题讨论】:
-
输出将只包含一个总是第一个或有时是第二个?
-
您没有展示
out是什么或您如何创建它。请添加。 -
@ScaryWombat 我刚刚更新了我的问题,请看一下好吗?谢谢~
-
@Hearen 是的,同意,但由于主线程已经完成,将不再工作。例如在 Jshell 上尝试同样的事情,你总是会得到两个输出,但第二个输出有时会作为另一个命令,这是因为主线程没有等待子线程关闭并完成,因此 jshell 移动到下一个命令可以看到其他输出的行
-
请阅读并回复上面的第二条评论。我猜
main线程会隐式打开和closesout
标签: java multithreading junit junit4 println