Search code examples
javajavafxandroid-asynctaskexecutorservicejava.util.concurrent

JavaFX app that uses Executor hangs on quit


I'm trying to make a clone of Android's AsyncTask to use in a JavaFX app. Here's the code I've come up with:

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

abstract public class AsyncTask<Param, Result>
{
    private Param param;
    private static Executor executor;

    public AsyncTask()
    {
        if (executor == null)
            executor = Executors.newSingleThreadExecutor();
    }

    protected void onPreExecute()
    {

    }

    protected Result doInBackground(Param param)
    {
        return null;
    }

    protected void onPostExecute(Result result)
    {

    }

    final public void execute(Param param)
    {
        this.param = param;

        onPreExecute();

        Task t = new Task();
        executor.execute(t);
    }

    private class Task implements Runnable
    {
        public void run()
        {
            Result result = doInBackground(param);
            onPostExecute(result);
        }
    }
}

I can use this class in my JavaFX app and it works fine except for one thing: when I close the main window, the JVM hangs rather than exiting cleanly. I have to force-quit the app.

I think the problem is related to the Executor. Because I don't issue a shutdown(), the Executor hangs waiting for more tasks to execute. Because AsyncTask is a wrapper for Java's Executor, the class that extends AsyncTask won't have direct access to the Executor and therefore can't issue a shutdown(). How can I do an orderly shutdown of the Executor?


Solution

  • You either need to shutdown the executor from the Application.stop method or you make sure the Executor's thread won't prevent the JVM from shutting down by using a daemon thread:

    if (executor == null) {
        executor = Executors.newSingleThreadExecutor(r -> {
            Thread t = new Thread(r);
            t.setDaemon(true);
            return t;
        });
    }