In this tutorial we’re going to look at one of the parts of JavaFX that causes the most headaches for beginners - background threads and the FXAT.

In my experience, every JavaFX programmer “knows” you cannot do long operations on the FXAT. Yet every newbie programmer breaks this rule at every opportunity. Over and over again.

Sometimes, it looks like you can get away with it. Maybe your development environment has a local development database with only a couple of programmers using it. The response time is a few milliseconds for just about any request. Your screens work fine, even when you load your data on the FXAT.

Then you move it into production. Now the database is running somewhere in the cloud with thousands of active users. The network latency alone adds a guaranteed 50ms overhead to every request. Your application makes 100 back-to-back API calls to load your data. It took 600ms in development, now it’s 5500ms. That’s 5.5 seconds! Your GUI just hangs for 5.5 seconds. What went wrong? The phone starts to ring as the support tickets come in…

You need to understand how to use the FXAT properly.

What is the FXAT, Anyway?

All of the various elements that make up the JavaFX screens are not thread-safe. This means that they have no programming baked into them to handle concurrency issues that might arise from having separate threads accessing the same data elements at the same time, possibly changing values, while another thread is relying on the previous value. Undoubtedly, this has greatly simplified the design of all of these classes, and the authors of JavaFX have had to ensure that the screens don’t become slow and unresponsive when being serviced by only a single thread.

The FXAT is the “JavaFX Application Thread”, and it’s the mechanism by which JavaFX can be a single threaded library. It’s a single process which is started up automatically when you execute the launch() method in your Application class. From that point on, everything that has to do with the GUI needs to run on that single thread.

From the JavaDocs for Application

JavaFX creates an application thread for running the application start method, processing input events, and running animation timelines. Creation of JavaFX Scene and Stage objects as well as modification of scene graph operations to live objects (those objects already attached to a scene) must be done on the JavaFX application thread.

How the FXAT Works

Basically, it’s an infinite loop that checks a queue for jobs and executes them in order. Each “job” is a snippet of code (ie: a Runnable), that’s been triggered by some kind of Event or manually submitted to the queue.

One of the big things to remember about this system is that there’s no connection in time between when a job is submitted to the FXAT and when it will run. It might run very quickly, or the queue may already have hundreds of jobs in it. You don’t know. You cannot know.

The impact of this is that while you can count on code which is contained within a single job on the FXAT being executed sequentially, you cannot assume that two jobs submitted back-to-back will be executed back-to-back. So each job should be complete within itself.

Jobs submitted to the FXAT will be run in order, but there’s no guarantee that other jobs won’t be slipped in between two jobs. This means that the GUI environment could change, and could change a lot, between the time that a job is triggered and the time that it executes. This can become a critical design consideration.

How to Submit Jobs to the FXAT

There’s two ways to get your code into the FXAT queue:

Attach an EventHandler to a Node or Object.
Pretty much any place that you see a method in a JavaFX object called setOn...() you are going to be defining an EventHandler. And that EventHandler will be submitted to the FXAT queue each time that Event is triggered on that object.
Call Platform.runLater()
This is how you manually submit a job to the FXAT. It’s called “runLater” because that’s exactly what it does, it put’s your job onto the back end of the FXAT queue where it will be run when it hits the front of the queue.

Things You Shouldn’t Do on the FXAT

There are two basic classifications of operations that should never be done on the FXAT.

Operations that take more than a few milliseconds to complete.
I’d set the limit at about 10 milliseconds, but that might be a bit conservative. There’s a lot that can be done in that much time, and in truth you probably wouldn’t even be looking to see how long something took unless you were experiencing issues with your GUI.
Blocking (or Potentially Blocking) Operations.
A blocking operation is anything that potentially executes a wait() operation or its equivalent. This includes virtually every file operation, every database operation, and any calls to API’s that might wait(). Blocking operations are particularly brutal on the FXAT because they can last for seconds at a time, during which the GUI is completely frozen. Also, blocking operations can be highly variable, and might be fast in your test environment but subject to delays at times in production.
primary

While the FXAT is running your code it's not doing anything else.

This means that it’s not responding to mouse events, clicks, keystrokes, or anything else. New jobs submitted via Platform.runlater() or as EventHandlers are going to sit at the bottom of the queue until your code completes. Your GUI is effectively frozen until your code is finished.

Starting Background Threads with Task

OK, so you’ve decided that some piece of code needs to be run off the FXAT. How do you do this?

JavaFX has a tool designed just for this: Task.

Task is an abstract generic class that has methods for communicating between a background thread and the FXAT and a single abstract method name call().

In the JavaDocs for Task there’s a fairly long description section. It’s accurate, but also pretty much rubbish unless you already understand how to use Task. There’s only a passing mention of the most useful use-case for Task, which is to run a job to completion, at which point some code is executed on the FXAT - possibly using the results from call().

Generally speaking, you’ll use Task as an anonymous inner class, so you’ll have access to all of the data available in the scope in which the Task is defined.

primary

You need to be careful if your Task accesses data updated by the FXAT as it may have changed between the time that the Task was invoked and the time that the code in call() runs.

This tutorial is really about the FXAT and how to deal with it. So we’re not going to go into all of the cool features of Task (or Service) and updating progress and all that. We’re going to concentrate on the mechanics of getting off the FXAT and then back onto it through Task.

A Simple Example

The most straight-forward use for Task is to run some process that produces data as a result, and then use that data to update your GUI.

The Simulated API

The JavaDocs for Task have a lot of examples with loops and sleep(), but in order to keep it clear how this fits with something more real-life, with the blocking code at arms-length from layout code, I’ve created a simulated API class. This allows us to call it and just assume that it’s doing something external which is going to take some time to complete or may possibly block.

public class FxatApi {

    public String remoteCall(String theAnswer) {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return theAnswer;
    }
}

It’s very simple, and it just echoes back whatever is passed to it after a 3 second delay. We’re going to use this same simulated API for all of the examples.

The Layout

Here’s the actual screen. It’s just a Label and a Button in a VBox. The application has a Presentation Model, and that’s a single StringProperty. This is just enough skeleton to demonstrate how Task works.

public class FxatDemo1 extends Application {

    private final StringProperty stringProperty = new SimpleStringProperty("Starting Value");

    public static void main(String[] args) {
        launch();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setScene(new Scene(createContent()));
        primaryStage.show();
    }

    private Region createContent() {
        Label label = new Label();
        label.textProperty().bind(stringProperty);
        Button button = new Button("Click Me");
        button.setOnAction(evt -> callApi());
        VBox results = new VBox(20, label, button);
        results.setPadding(new Insets(20));
        return results;
    }
}

The Task

This method is actually part the FxatDemo1 class, but I’ve split it out here so that it’s clear how it’s operating:

private void callApi() {
    Task<String> apiTask = new Task<String>() {
        @Override
        protected String call() throws Exception {
            return new FxatApi().remoteCall("The Answer");
        }
    };
    apiTask.setOnSucceeded(evt -> stringProperty.set(apiTask.getValue()));
    Thread apiThread = new Thread(apiTask);
    stringProperty.set("Running API...");
    apiThread.start();
}

Here we create a Task which returns a String, and then set its call() method to instantiate our dummy API and call its remoteCall() method. The Task has an EventHandler added to it, triggered on its OnSucceeded event. That event handler grabs the value calculated by call() and sets it in the Presentation Model.

info

Task's call() method runs on the background thread and produces results that can be retrieved later via the Task's getValue() method.

Finally, a new Thread is created for the Task and it is started on it. Just before it is launched, the value in the StringProperty is changed to “Running API…”. This way we can see when the Task starts, and when it ends.

primary

All of the code in this method except for that single line inside of the Task's call() method executes on the FXAT at time that the Button's click action runs.

Understanding what-code-runs-when-and-where is a key element in using the FXAT properly.

The Output

Initially, the screen looks like this:

ScreenShot 1

Then, as soon as the Button is clicked, it changes to this:

ScreenShot 2

And then it ends like this 3 seconds later:

ScreenShot 3

And that’s just about the most simple and common use for Task in JavaFX.

onSucceeded, onFailed, and onCancelled

The example above uses setOnSucceeded() to fire an EventHandler that runs when the Task completes. This gets you back on the FXAT and runs when the value calculated by call() on the background thread is available.

Now, if you look at the JavaDocs, you’ll see that there’s a couple other events that might be fired when call() ends. These are OnFailed, and OnCancelled. If your Task can end with OnSucceeded, can’t it end with these other events, too?

There was a time when I felt I was obliged, for the sake of tying up all the loose ends, to deal with these other two events. But I’ve come to realize that this isn’t necessary.

First, from what I’ve been able to determine, OnFailed will only be triggered when the code in call() throws an uncaught exception. Generally speaking, an exception in a background task is either a nothing, or it’s a something that you really should deal with in some explicit way and may involve updating the GUI to let the user know what’s happened. If you do need to update the GUI after an exception, then OnFailed is probably the way to go, as it will execute on the FXAT and allows you to access the exception, too.

Cancelling a running Task is a pretty specific and potentially complicated operation. It can’t happen unless you deliberately program it in. And if you don’t do this, you don’t need to worry about OnCancelled.

The Juggler

A lot of programmers have a great deal of difficulty envisioning how the background tasks work and the impact to their application logic.

The One Thing That you Cannot Do…

You can’t write anything that looks like a Function. What I mean by this is some construct that accepts input data and then returns a value derived from it. Once you spawn a background thread, this linear approach is off the table. There’s no way that you can implement it without executing wait() on the FXAT somehow, and that’s an absolute “no-no”.

warning

All new JavaFX programmers try to do this.

It can't be done but, go on...try now.

Continue reading when you give up.

Now, About Juggling

The analogy that helped me cope with this was to think about it like a juggler. So, picture a juggler…

At any given time, he’s got some number of balls in the air, and one of them is on it’s way down and needs to be caught and tossed back into air very soon. He might have special rules about how to handle the balls. Like, say… “the blue ball needs to be bounced off his knee every time”, and, “the green ball needs to be thrown twice as high as the other balls”.

Whatever the instructions, he can’t take very long with any particular ball or he’s going to miss handling the next ball coming down, and the whole performance will come to an end. An instruction like, “grab a pen and write your name on the ball before you toss it”, is out of the question.

Obviously, the juggler is the FXAT and the balls are the Runnables that are being dumped into the queue all of the time. It’s not a perfect analogy, but it’s close enough to give some pretty solid guidelines about how to program around the FXAT.

Now, imagine that the juggler has an assistant or another juggler with him.

From time to he’ll toss one of his balls off to that assistant, and then some time later the assistant will toss a ball back to him. When that happens, he has to be able to handle it and integrate it into the balls that he’s currently juggling without dropping any of them.

But here’s the important part: He doesn’t know when, or even if, the assistant is going to toss a ball back. So he cannot wait for it. He has to keep juggling his other balls, and when the new ball comes to him, whenever that happens, he has to deal with it.

This is How You Need to Think About Background Tasks

Running a background task is just like tossing a ball off to an assistant. You package up your code to run and hand it off to the background task. At the same time, you need to write the code that will be executed to handle the event that’s triggered when the background task completes (or fails).

You can’t wait for it. You cannot make any assumptions about when it’s going to happen. You cannot make any assumptions about the state of your GUI when it happens. You cannot make any assumptions about which background task will complete first.

This is what you are doing when you write an EventHandler for OnSucceeded. You’re writing the instructions for how to handle whatever information has been updated by your Task. You don’t know when, or even if, that will happen. But this is what you want to have happen on the FXAT when it does.

Another Approach to Task

Personally, I prefer to have all of the business logic off in its own class, something I have been calling an Interactor. With this structure the Interactor has access to the Model, and can update it. But, since it still needs the thread handling of Task there are two public methods, one to call the API and another to update the Model:

public class FxatInteractor {

    private final StringProperty model;
    private String domainData;

    public FxatInteractor(StringProperty model) {
        this.model = model;
    }

    public void fetchApiData() {
        domainData = new FxatApi().remoteCall("The Answer");
    }

    public void loadModel() {
        model.set(domainData);
    }
}

The method fetchApiData() is intended to be called on a background thread, and it simply calls the API and stores the result in the field, domainData. The method loadModel() is called on the FXAT and updates the Model with the data previously fetched from the API on the background thread.

Note that the Interactor is aware of the FXAT, but only at arms length. The code is divided up into things that shouldn’t happen on the FXAT and things that should happen on the FXAT. But there’s no code that actually deals with the FXAT.

Here’s callApi() from the main class:

private void callApi() {
    Task<Void> apiTask = new Task<>() {
        @Override
        protected Void call() {
            interactor.fetchApiData();
            return null;
        }
    };
    apiTask.setOnSucceeded(evt -> interactor.loadModel());
    Thread apiThread = new Thread(apiTask);
    stringProperty.set("Running API...");
    apiThread.start();
}

Additionally, interactor is instantiated as a field in the main class, and it’s given a reference to the Model:

private final FxatInteractor interactor = new FxatInteractor(stringProperty);

The Task now has a type of Void, as the method call() no longer needs to return anything. The Interactor will update the Model directly.

Dealing With Concurrency Issues

As soon as you start launching threads you absolutely have to start worrying about concurrency issues. There’s no way around this. For this example, there are two basic ways to cope with concurrency…

Method 1: Prevent Multiple Background Threads

The domain data is at risk here because it could be updated by multiple threads simultaneously. One way to guard against this it to structure the application in such a way that only one background thread can be run at a time. Since the background thread in this example is only launched when the Button is clicked, we can ensure that Button cannot be clicked again until the background thread has completed:

private Region createContent() {
   Label label = new Label();
   label.textProperty().bind(stringProperty);
   Button button = new Button("Click Me");
   button.setOnAction(evt -> {
       button.setDisable(true);
       callApi(() -> button.setDisable(false));
   });
   VBox results = new VBox(20, label, button);
   results.setPadding(new Insets(20));
   return results;
}

We disable the Button as soon as it has been clicked, then create a Runnable that will re-enable it. We pass that Runnable to the callApi() method.

private void callApi(Runnable postFetchAction) {
   Task<Void> apiTask = new Task<Void>() {
       @Override
       protected Void call() {
           interactor.fetchApiData();
           return null;
       }
   };
   apiTask.setOnSucceeded(evt -> {
       interactor.loadModel();
       postFetchAction.run();
   });
   Thread apiThread = new Thread(apiTask);
   stringProperty.set("Running API...");
   apiThread.start();
}

The only change here is that we now take a Runnable as a parameter, and call its run() method in the OnSucceeded event handler. This will do the trick and it’s really not a bad approach. In most cases, you probably won’t want to keep open the possibility that the user will re-run whatever process is kicked off by the the Button until it’s finished anyways.

Perhaps even more important, though, is how this example demonstrates a clean way to handle this very, very common pattern around Button handling - especially if the Button is doing a “Load” or a “Save” type function. Note how the actions which are internal to the View are all contained inside the View, and the callApi() method has no knowledge of the inner structure of the View.

Method 2: Isolate the Data for Each Thread

private void callApi() {
    Task<FxatInteractor> apiTask = new Task<>() {
        @Override
        protected FxatInteractor call() {
            final FxatInteractor interactor = new FxatInteractor(stringProperty);
            interactor.fetchApiData();
            return interactor;
        }
    };
    apiTask.setOnSucceeded(evt -> apiTask.getValue().loadModel());
    Thread apiThread = new Thread(apiTask);
    stringProperty.set("Running API...");
    apiThread.start();
}

Here the Interactor is treated as a single-purpose business logic class. It’s instantiated inside of the Task’s call() method and returned as the value so that setOnSuccedded() can retrieve it on the FXAT. This means that every time our Task is started, it will create a brand new Interactor and there’s no possible concurrency issues with the updating of domainData.

This method is really valuable when you have a background task that can be triggered frequently and concurrently. For instance, you may have a ListView and trigger your Task whenever a new row becomes selected. A user scrolling down through the ListView by holding down an arrow key could trigger many, many Tasks in a very short period of time. In a case like that, though, you probably want to look into using Service instead of Task since it uses a ThreadPool to limit the number of active background threads.

Avoiding Platform.runLater()

If you look out there on the Internet you’ll find tons and tons of examples with Platform.runLater() scattered willy-nilly all over the code. Heck, even the JavaDocs for Task has them. Yuck!

There’s really nothing wrong with Platform.runLater() per se, and you’ll see it used in examples all over the web. It works, and it works well.

My observation, however, is that Platform.runLater() can be a bit of a code smell and often indicates some deeper issue with the design of a system. So I personally leave Platform.runLater() as the last alternative to get code back on the FXAT, and only use it when I can’t find a better way. I think the result is a more coherent, well thought out, JavaFX design.

Platform.runLater() is best used when you really need to return partial results. Not progress tracking, but actually returning results and incorporating them into the GUI as they are generated.

If you’re using Task, and you’re not returning partial results, there’s really no valid reason to use Platform.runLater(). If you are just manually launching a Thread to execute some Runnable, you probably should be using Task instead. There’s very little extra work involved in defining a Task, and the structure clearly declares what you’re doing for anybody who comes along looking at your code.

Another Use for Platform.runLater()

Sometimes you just need to make sure that some aspect of what you’re doing to your GUI needs to happen at the end of everything. It’s entirely possible that something in your code is going to trigger an Event, or the internal handling of some GUI element is going to have some side-effect you have to ensure is completed before some part of your code.

Maybe there’s some background process that’s generating partial results, or which might complete while your code is running, and you want to make sure that some piece of your code runs after these results have been handled.

In these cases, you’re already writing code that’s running on the FXAT, and Platform.runLater() can be the answer. It’s right there in the name runLater(), “run later”!

There’s a reason it’s called this. Any Runnable that you submit to Platform.runLater() is added to the end of the FXAT job queue. Meaning that it will get run after any Events that your code has already triggered. It will run after any other jobs that have already been submitted via Platform.runLater(), perhaps from a background Task.

In practice, you’ll need this technique only rarely. Sometimes you’ll come across a case where sticking part of your code inside a Platform.runLater() seems to fix a problem. But it will often turn out not the best solution to the problem, and if you come back and look at the code later, after you’ve learned more about how JavaFX works, you might see what’s really going on.

Categories:

Updated: