23

我在关闭我的应用程序时遇到问题,因为在我关闭应用程序后某些线程仍在运行。有人可以帮助我用一些方法在杀死主线程之前停止所有线程在后台执行???

[编辑]

关于 javafx 的问题,我注意到许多新开发人员都面临管理线程的问题。我想分享我为简化在 javafx 上管理线程的生活所做的工作。我创建了一个基于 Android 的 AsyncTask 的 AsyncTask 类,它基本上以一种简陋但有效的方式与 Android 相同。您可以在Github 项目上找到有关它的更多信息

4

5 回答 5

38

解决此问题的更好方法是在Close Request上添加EventHandler

@Override
public void start(Stage primaryStage) {
    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
       @Override
       public void handle(WindowEvent e) {
          Platform.exit();
          System.exit(0);
       }
    });
}
于 2013-12-04T11:54:09.803 回答
37

您在这里有三个选项 - 最简单的方法是将线程创建为守护进程,这意味着当您的主程序结束时,所有守护线程也将终止。

Thread thread = new Thread();
thread.setDaemon(true);

这是最简单的,但缺点是你不会得到一个正常的关闭(即线程将停止,你不会有机会执行资源管理等,这对你来说可能是也可能不是问题)。

另一种方法是保留生成的线程,当您的程序收到关闭信号时,您遍历线程并传递某种信号以表示它们也应该终止

volatile boolean shutdown = false;

public void shutdown() {
   shutdown = true;
}

public void run() {
    while(!shutdown) { 
        ... do your work here
    }
    ... perform any cleanup work here

(注意:为清楚起见,忽略任何异常处理)

最后一个选项是使用 java.util.concurrent 中的 Executor 框架

ExecutorService executorService = Executors.newFixedThreadPool(10);
... assign/invoke tasks etc

... at some point later your program is told to shutdown 
... shutdown in executor too 
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS); // wait for 10s in this case
executorService.shutdownNow();
于 2013-02-15T15:01:05.440 回答
5

覆盖您的应用程序类

//System.exit(0) This will close all timers and threads inside the Jar application...
@Override
public void stop() throws Exception {
    super.stop(); //To change body of generated methods, choose Tools | Templates.
    System.exit(0);
}
于 2018-01-14T16:46:20.967 回答
2

包中的执行者java.util.concurrent要走的路。明确地:

ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactory() {
     @Override
     public Thread newThread(Runnable runnable) {
          Thread thread = Executors.defaultThreadFactory().newThread(runnable);
          thread.setDaemon(true);
          return thread;
    }
});

具有固定ScheduledExecutorService的 Java 8 版本

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, r -> {
    Thread thread = Executors.defaultThreadFactory().newThread(r);
    thread.setDaemon(true);
    return thread;
});
于 2017-04-24T19:18:47.790 回答
2

方法 Platform.exit() 属于 JavaFX 上下文。当您调用 Platform.exit() 时,方法 javafx.application.Application#stop() 在上下文终止之前被调用。将 JavaFX 上下文终止之前需要执行的所有内容放入 stop() 方法中。

使用 System.exit(0) 方法,应用程序会突然终止。此方法不安全,因为如果此时您调用 System.exit(0) 并且作业仍在运行,可能正在数据库中执行写入操作,应用程序将不会等待作业文件,从而导致数据库损坏。

我有一个使用 SpringBoot 和线程池运行 JavaFX 的应用程序。我就是这样处理的。

//...
import javafx.application.Application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

@SpringBootApplication
public class Main extends Application {

    ConfigurableApplicationContext context;

    ScheduledExecutorService scheduledExecutorService;


    @Override
    public void init() {

        this.context = SpringApplication.run(getClass());

        this.context.getAutowireCapableBeanFactory().autowireBean(this);

        this.scheduledExecutorService = Executors.newScheduledThreadPool(10);

    }

    @Override
    public void stop() throws Exception {

        super.stop();

        this.context.close();

        this.scheduledExecutorService.shutdownNow();

    }


    // ...

}
于 2018-12-29T16:19:31.853 回答