У меня есть простая тестовая программа (симуляция гаража) с несколькими потоками (объекты Vehicle
, MysteryVehicle
, Observer
), созданными и запущенными. Только объект Observer
представляет собой поток демона, работающий в бесконечном цикле.
После завершения всех потоков, не являющихся демонами, поток Observer
никогда не завершается, и цикл выполняется бесконечно (так что это не какой-то буферизованный вывод после того, как поток демона на самом деле завершается — он продолжается вечно).
Все потоки, не являющиеся демонами, выводят что-то на консоль непосредственно перед выходом из своих run()
методов, и это ясно показывает, что все они действительно завершены. Я также не вызывал join()
в потоке демона. При распечатке всех запущенных в данный момент потоков также отображается observer
, поэтому я предполагаю, что этот поток демона не завершается должным образом.
Полный код можно найти в этой фиксации.
Ниже вы можете увидеть все темы, созданные, запущенные и где именно вызывается join()
.
Main.java
package garage;
import java.util.Set;
import garage.model.*;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
Platform platform = new Platform();
Vehicle.platform = platform;
platform.print();
Vehicle[] vehicles = new Vehicle[30];
for (int i = 0; i < 30; i++) {
vehicles[i] = new Vehicle();
}
for (int i = 0; i < 30; i++) {
vehicles[i].start();
}
Observer observer = new Observer();
observer.platform = platform;
observer.start();
MysteryVehicle mysteryVehicle = new MysteryVehicle();
mysteryVehicle.start();
try {
mysteryVehicle.join();
} catch (Exception exception) {
exception.printStackTrace();
}
try {
for (int i = 0; i < 30; i++)
vehicles[i].join();
} catch (Exception exception) {
exception.printStackTrace();
}
System.out.println("before");
platform.print();
System.out.println("after");
synchronized (Platform.lock) {
System.out.println("END");
System.out.println(platform.flag); // checks whether wait() was called anytime
}
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread t : threads) {
System.out.println(t.getName());
}
}
public static void main(String[] args) {
launch(args);
}
}
Observer.java
package garage.model;
public class Observer extends Thread {
public Platform platform;
static int count = 0;
{
setName("observer");
setPriority(MIN_PRIORITY);
setDaemon(true);
}
@Override
public void run() {
while (true) {
synchronized (Platform.lock) {
try {
System.out.println(++count);
platform.print();
Platform.lock.wait(5000); // hack for when there is no meaningful loop condition
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
Platform.lock.notifyAll();
}
}
}
}
}
Метод Vehicle run() – соответствующая часть
public void run() {
...
System.out.println("done");
}
Метод MysteryVehicle run() – соответствующая часть
public void run() {
synchronized (Platform.lock) {
System.out.println("And the vehicle disappears!");
...
}
}
Все соответствующие сообщения потока выводятся на консоль. сделано - 30 раз, И машина исчезает!, до, после, КОНЕЦ, правда
Это список всех запущенных потоков:
Attach Listener
main
Common-Cleaner
JavaFX Application Thread
Signal Dispatcher
Finalizer
InvokeLaterDispatcher
Reference Handler
QuantumRenderer-0
observer
Thread-2
JavaFX-Launcher
Поскольку программа не завершается, а функция print()
вызывает run()
метод observer
, что мешает завершению потока демона?
Что мне здесь не хватает?
Platform.exit()
не вызывается, и нет никаких объектов пользовательского интерфейса, которые нужно закрыть, поэтому действительно ли возвращаетсяmain()
? Попробуйте добавитьprintln()
послеlaunch()
. - person Andrew S   schedule 21.12.2018main()
вызывается потоком, не являющимся демоном. - person Solomon Slow   schedule 21.12.2018