Posts Tagged ‘Concurrency’

Custom Asynchronous Tasks in JavaFX

August 26th, 2009

As I mentioned in my previous blog, during my experiments with JavaFX I needed to run certain tasks on a separate thread (e.g. calls to a remote web service via Jersey Client API). One can do it in JavaFX using JavaTaskBase class, but I wanted something simpler, something similar to what FXexperience blog suggested. So, I created a custom subclass of javafx.async.Task named AsyncTask that allowed me to make asynchronous calls as follows:

    AsyncTask {
        run: function() {
            // add the code you want to run asynchronously
        }

        onDone: function() {
            // this is executed once the "run" method finishes running
        }
    }.start();

Here is the source code for the AsyncTask class together with the helper Java class it’s using. It should be self explanatory.

AsyncTask.fx
import javafx.async.Task;

public class AsyncTask extends Task, AsyncTaskHelper.Task {
    /** Function that should be run asynchronously.
     */
    public var run: function() = null;

    // the helper
    def peer = new AsyncTaskHelper(this);

    // used to start the task
    override function start() {
        started = true;
        if (onStart != null) onStart();
        peer.start();
    }

    // don't need stop - isn't implemented
    override function stop() {
        // do nothing
    }

    // called from the helper Java class from a different thread
    override function taskRun() {
        // run the code to be run asynchronously
        if (run != null) run();
        // send a notification (on the dispatch thread) the code finished running
        FX.deferAction(function() {
            done = true;
            if (onDone != null) onDone();
        });
    }
}
AsyncTaskHelper.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AsyncTaskHelper implements Runnable {
    // Using a fixed threadpool to run the asynchronous task
    private static final ExecutorService QUEUE = Executors.newFixedThreadPool(10);
    // the "parent" JavaFX AsyncTask instance
    private final Task peer;

    public AsyncTaskHelper(Task peer) {
        this.peer = peer;
    }

    // called from AsyncTask.start() method - will add this task
    // to the thread pool queue
    public void start() {
        QUEUE.execute(this);
    }

    // called by the thread pool queue to start the task
    public void run() {
        peer.taskRun();
    }

    // interface to be implemented by the "parent" JavaFX AsyncTask
    public static interface Task {
        public void taskRun();
    }
}