У меня небольшой тест с использованием двух потоков следующим образом:
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 thread, по умолчанию являются пользовательскими потоками, а пользовательские потоки не завершаются пока они не закончат.
Хотя я использую @ Test , я проверил, что они не-демон , как и ожидалось.
не-демон
является потоком демона, если и только если создающий поток является демоном
И
Виртуальная машина Java продолжает выполнять потоки, пока не произойдет одно из следующих действий:
Вызван метод выхода класса Runtime, и менеджер безопасности разрешил выполнение операции выхода.
Все потоки, которые не являются потоками демонов , умерли, либо возвращаясь из вызова метода run, либо выбрасывая исключение, которое распространяется за пределы метода run.
ОБНОВЛЕНО
На самом деле я знаю, на что указывают ответы, мне интересно, почему вывод исчезает?
Вопросы, которые мне нужно задать:
Трубопровод , закрытый основным потоком?
Почему? Это потому, что каждый конвейер связан с одним потоком независимо? Не поделился? (что конвейер не будет закрыт до тех пор, пока не закончится последний поток, как подсчет ссылок - файл не будет удален, пока его никто не использует)
- Последний вопрос: управляется ли он JVM или зависит от ОС?
Кажется, конвейер закрыт по @Test
, который я упомянул. Спасибо, @meriton за то, что указал на это.
Заключение
Когда я попробовал этот метод в обычном main()
и сразу вызвал System.exit(0);
сразу после start()
, вывод будет таким же, как при использовании @Test
.
При использовании @Test
(Junit) потоки не будут ждать. Для получения более подробной информации, пожалуйста, проверьте Тест JUnit не выполняет все потоки, созданные в тесте , и JUnit завершает дочерние потоки .
А вот объяснение от @Alex Lockwood, которое я лично предпочитаю:
JUnit - это фреймворк для юнит-тестирования ... как и в фреймворке Android, он имеет основной поток, из которого он будет вызывать определенные пользователем методы юнит-тестирования. Когда модульный тест возвращается, JUnit немедленно вызывает следующий метод модульного теста (или завершается полностью, если больше нет методов для модульного теста, которые нужно вызвать). JUnit ничего не знает о фоновых потоках, которые вы создаете / запускаете, поэтому вы не можете предполагать, что он будет сидеть сложа руки и ждать их завершения.