具有无限循环的守护程序线程不终止

时间:2018-12-21 14:59:38

标签: java multithreading

我有一个简单的测试程序(车库模拟),该程序带有多个实例化并启动的线程(VehicleMysteryVehicleObserver对象)。只有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方法是无限执行的,它是什么防止守护线程终止?

我在这里想念什么?

2 个答案:

答案 0 :(得分:0)

据我所知,在守护程序线程上调用join是一个坏主意。使用守护程序线程的想法是它不会阻止JVM退出。您可以做的是向该线程发送中断,然后再调用join。

答案 1 :(得分:0)

我怀疑main()永不返回,因此 main 线程(可能还有一些FX线程)仍在运行。

来自Application doc

  

在应用程序退出之前,启动方法不会返回,   通过调用Platform.exit或所有应用程序窗口   已关闭。

发布的代码没有关闭窗口,也不会调用Platform.exit()