JavaFX Task threads not terminating

我们两清 提交于 2019-12-07 06:10:24

问题


I am writing a JavaFX application and my objects extend Task to provide concurrency away from the JavaFX GUI thread.

My Main class looks like this:

public class MainApp extends Application {

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));        
    Scene scene = new Scene(root);       
    stage.setScene(scene);
    stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        public void handle(WindowEvent t) {
            //I have put this in to solve the threading problem for now.
            Platform.exit();
            System.exit(0);
        }
    });
    stage.show();
}

public static void main(String[] args) {
    launch(args);
}
}

My GUI Controller Sample looks like this (abstracted slightly):

ExecutorService threadPool = Executors.newFixedThreadPool(2);
private void handleStartButtonAction(ActionEvent event) {
        MyTask task = new MyTask();
        threadPool.execute(task);
}

At the moment my task just does a sleep and prints numbers 1 through 10:

public class MyTask extends Task<String> {

@Override
protected String call() throws Exception {
    updateProgress(0.1, 10);
    for (int i=0;i<=10;i++) { 
        if (isCancelled()) {
            break;
        }
        Thread.sleep(1000);
        System.out.println(i);
        updateProgress(i, 10);  
    }  
    return "Complete";      
}
}

The problem I have is once the task completes it appears as though the thread the task is launched with continues to run. So when I exit the JavaFX application by pressing the "X" top right corner, the JVM continues to run and my application does not terminate. If you look at my main class, I have put in System.exit() which seems to solve the problem though I am aware this is not the correct way.

Can someone suggest what I need to do in terms of terminating my child threads, and what is the accepted way of doing this? i.e, checking they are complete and then terminated for example.

Thanks


回答1:


The Javadocs for Executors.newFixedThreadPool() state that:

The threads in the pool will exist until it is explicitly shutdown.

Also check the the usage examples of ExecutorService, they take care to always shutdown the pool.

You probably have to ensure that threadPool.shutdown() is called at the appropriate place of your application.




回答2:


The approach that Nikos provides (invoking shutdown) is good and straight-forward.

An alternate is to define your own thread factory for thread creation. In your thread factory, make the threads daemon threads. A JavaFX program stops when all non-daemon threads have completed (which means that your program will exit even if you don't explicitly shutdown the thread pool for your ExecutorService).

ExecutorService threadPool = Executors.newFixedThreadPool(
    2, 
    new ThreadFactory() {
        AtomicInteger a = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, "mythread-" + a.getAndIncrement());
            t.setDaemon(true);
            return t;
        }
    }
);

Daemon threads aren't appropriate for all services, sometimes explicit shutdown handling is better.

The daemon thread factory approach is used in a few places in the JDK.



来源:https://stackoverflow.com/questions/22657192/javafx-task-threads-not-terminating

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!