我有一个简单的测试程序(车库模拟),该程序带有多个实例化并启动的线程(Vehicle
,MysteryVehicle
,Observer
对象)。只有Observer
对象是运行无限循环的守护程序线程。
在所有非守护程序线程终止之后,Observer
线程将永远不会执行并且循环将无限执行(因此,这不是守护程序线程 really 终止后的某些缓冲输出-它确实永远继续下去。
所有非守护进程线程都在退出它们的run()
方法之前向控制台打印一些内容,它清楚地显示了所有它们实际上已终止。我也没有在守护程序线程上调用join()
。当打印出所有当前正在运行的线程时,也会列出observer
,因此我猜测此守护程序线程未正确终止。
完整的代码可以在this commit上找到。
在下面,您可以看到所有创建,启动的线程以及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();
}
}
}
}
}
车辆run()方法-相关部分
public void run() {
...
System.out.println("done");
}
MysteryVehicle run()方法-相关部分
public void run() {
synchronized (Platform.lock) {
System.out.println("And the vehicle disappears!");
...
}
}
所有相关的线程消息都被打印到控制台。 完成-30次,车辆消失了!,之前,之后, END , true
这是所有正在运行的线程的列表:
Attach Listener
main
Common-Cleaner
JavaFX Application Thread
Signal Dispatcher
Finalizer
InvokeLaterDispatcher
Reference Handler
QuantumRenderer-0
observer
Thread-2
JavaFX-Launcher
由于程序没有终止,并且print()
调用的run()
方法的observer
方法是无限执行的,它是什么防止守护线程终止?
我在这里想念什么?
答案 0 :(得分:0)
据我所知,在守护程序线程上调用join是一个坏主意。使用守护程序线程的想法是它不会阻止JVM退出。您可以做的是向该线程发送中断,然后再调用join。
答案 1 :(得分:0)
我怀疑main()
永不返回,因此 main 线程(可能还有一些FX线程)仍在运行。
在应用程序退出之前,启动方法不会返回, 通过调用Platform.exit或所有应用程序窗口 已关闭。
发布的代码没有关闭窗口,也不会调用Platform.exit()
。