Stop threads before close my JavaFX program

后端 未结 5 1146
迷失自我
迷失自我 2020-12-14 17:05

I\'m having a problem with closing my application because some threads are still running after I close the application. Somebody can help me with some method to stop all Th

相关标签:
5条回答
  • 2020-12-14 17:37

    Override your Application Class

    //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);
    }
    
    0 讨论(0)
  • 2020-12-14 17:38

    Executors from the java.util.concurrent package are the way to go. Explicitly:

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

    Java 8 version with fixed ScheduledExecutorService

    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, r -> {
        Thread thread = Executors.defaultThreadFactory().newThread(r);
        thread.setDaemon(true);
        return thread;
    });
    
    0 讨论(0)
  • 2020-12-14 17:59

    You have three options here - the easiest is to simply create your Threads as deamons, which means that when your main program ends all deamon threads will terminate too.

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

    Thats easiest, but the downside is that you wont get a graceful shutdown (ie the threads will stop, you wont get a chance to peform resource management etc, which may or may not be a problem for you).

    The alternative is to keep a hold on the spawned threads and when your program receives the signal to close you iterate over the threads and pass in a signal of some sort to signa that they too should terminate

    volatile boolean shutdown = false;
    
    public void shutdown() {
       shutdown = true;
    }
    
    public void run() {
        while(!shutdown) { 
            ... do your work here
        }
        ... perform any cleanup work here
    

    (Note: ignores any exception handling for clarity)

    The last option is to use the Executor framework in java.util.concurrent

    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();
    
    0 讨论(0)
  • 2020-12-14 18:03

    Better way to fix this is add the EventHandler on Close Request:

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
           @Override
           public void handle(WindowEvent e) {
              Platform.exit();
              System.exit(0);
           }
        });
    }
    
    0 讨论(0)
  • 2020-12-14 18:03

    The method Platform.exit() belongs to the JavaFX context. When you call Platform.exit(), the method javafx.application.Application#stop() is called before the context terminates. Put inside the stop() method everything that needs to be executed before the JavaFX context terminates.

    With the System.exit(0) method, the application terminate abruptly. This method is not secure because if at the moment you call System.exit(0) and a Job is still running, maybe executing a write in the database, the application will not wait the Job fihish resulting in a corrupted database.

    I have an application running JavaFX with SpringBoot and a thread pool. That is how I handle it.

    //...
    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();
    
        }
    
    
        // ...
    
    }
    
    0 讨论(0)
提交回复
热议问题