Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop threads before close my JavaFX program

Tags:

java

javafx

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 Threads being executed in background before killing the main thread???

[EDITED]

With my questions about javafx I have noticed that many newer developers are facing problem managing Threads. I would like to share what I have done to simplify my life about managing threads on javafx. I've created an AsyncTask class based on AsyncTask from Android that basically do the same of Android's in a humble but effective way. You can find more information about it on Github project

like image 663
Victor Laerte Avatar asked Feb 15 '13 14:02

Victor Laerte


People also ask

How do you stop a thread in 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.

How do you end a JavaFX program?

exit(). The static exit() method in the Platform class is the preferred way to programmatically end a JavaFX program. It is preferred to System. exit() because it cleanly shuts down the application thread and gives it an opportunity to clean up by calling the application's stop() method before terminating.

Why is JavaFX not thread safe?

Thread safety in a JavaFX application cannot be achieved by synchronizing thread actions. We must ensure that the programs that manipulate the scene graph must do so only from the JavaFX Application Thread. Therefore, multithreading in JavaFX has to be handled in a different manner.

Are JavaFX properties thread safe?

The JavaFX scene graph, which represents the graphical user interface of a JavaFX application, is not thread-safe and can only be accessed and modified from the UI thread also known as the JavaFX Application thread.


4 Answers

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);
       }
    });
}
like image 186
Mirimas Avatar answered Oct 12 '22 14:10

Mirimas


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();
like image 44
Sean Landsman Avatar answered Oct 12 '22 13:10

Sean Landsman


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);
}
like image 5
guerino Avatar answered Oct 12 '22 15:10

guerino


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;
});
like image 4
Legato Avatar answered Oct 12 '22 14:10

Legato