【问题标题】:JavaFX Task threads not terminatingJavaFX 任务线程未终止
【发布时间】:2014-05-04 15:08:07
【问题描述】:

我正在编写一个 JavaFX 应用程序,并且我的对象扩展了 Task 以提供远离 JavaFX GUI 线程的并发性。

我的 Main 类如下所示:

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);
}
}

我的 GUI 控制器示例如下所示(略微抽象):

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

目前我的任务只是休眠并打印数字 1 到 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";      
}
}

我遇到的问题是,一旦任务完成,它看起来好像启动任务的线程继续运行。因此,当我通过按右上角的“X”退出 JavaFX 应用程序时,JVM 继续运行并且我的应用程序不会终止。如果你看看我的主课,我已经输入了 System.exit() 似乎可以解决问题,尽管我知道这不是正确的方法。

有人可以建议我在终止我的子线程方面需要做什么,以及这样做的可接受方式是什么?例如,检查它们是否完整然后终止。

谢谢

【问题讨论】:

    标签: multithreading javafx task


    【解决方案1】:

    Executors.newFixedThreadPool()Javadocs 声明:

    池中的线程将一直存在,直到它被显式关闭。

    同时检查ExecutorServiceusage examples,他们注意总是关闭池。

    您可能必须确保在应用程序的适当位置调用threadPool.shutdown()

    【讨论】:

      【解决方案2】:

      Nikos 提供的方法(调用关机)很好且直接。

      另一种方法是定义您自己的线程工厂来创建线程。在您的线程工厂中,创建线程守护程序线程。当所有非守护线程都完成后,JavaFX 程序就会停止(这意味着即使您没有明确关闭 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;
              }
          }
      );
      

      守护线程并不适用于所有服务,有时显式关闭处理更好。

      在JDK中的一些地方使用了守护线程工厂方法。

      【讨论】:

        猜你喜欢
        • 2017-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-15
        • 1970-01-01
        相关资源
        最近更新 更多