Most modern programs run operations in the background. Good applications do it all while maintaining an active interface with the user. Background tasks such as checking the status of a server, updating a local cache, or periodically setting off animations all need to be completed without causing the UI to hang.

Executing a periodic background task requires a timing mechanism, to set the periodicity, and a firing mechanism to set off the task itself. JavaFX provides three ways to execute background tasks periodically. In each case, JavaFX fires the task on the JavaFX Application thread, making it ideal for updating the user interface.

In order of increasing control and complexity, JavaFX’s default periodic mechanisms are:

  1. An AnimationTimer, with its handle() method.
  2. A Timeline object, with a registered KeyFrame and EventHandler
  3. A ScheduledService with a registered Task

The most effective mechanism for running a periodic task will depend on the efficiency you need and convenience you want for setting the timing.

Above, the list is in order of increasing convenience, and arguably decreasing efficiency.

On top of that, Java itself provides two ways to execute periodic background tasks. Because these will be executed outside of the JavaFX Application thread, they’re usually best use if you’re not using them to update the interface.

In order of increasing control and complexity, they are:

  1. A Timer with a registered TimerTask
  2. A ScheduledExecutorService and an associated Runnable

What you’ll get from this article

There are three ways to run a periodic task in the background in a way that’s compatible with updating the UI directly. Which one I use generally depends on three things:

  1. The efficiency you need,
  2. How much control you want to have over the task once it’s running, and
  3. Whether action is required if the task fails

Take a look at the three ways I usually think about running background tasks in JavaFX:

Timing MechanismEvent FiringUse case
AnimationTimerhandle()
  • Very low footprint mechanism
  • Manual event firing
  • Fire-and-forget
TimelineEventHandler
  • Automated timing
  • Automated event firing
  • Fire-and-forget
ScheduledServiceTask
  • Tasks which return data
  • Scheduling with automated error handling
  • Complex task progress monitoring

If you don’t need to update the user interface, you can obviously use any of the three options above. On top of that, there are also ways to run periodic background tasks which specifically will not run on the JavaFX application thread.

Timing MechanismEvent FiringUse case
TimerTimerTask
  • Simple repeated execution
  • Thread safe
  • No thread pooling
ScheduledExecutorServiceRunnable
  • Highly configurable
  • Automated thread pooling

In the following sections, I’ll go through each in turn, how to create it, and how to use it.

1. AnimationTimer

The most low-footprint way to run a background process in JavaFX is to create an AnimationTimer. Both the Timeline and the AnimationTimer feed off JavaFX’s AnimationPulse, which fires once per frame. By default that’s 60 times per second, but you can test how fast it is on your system.

An animation timer recieves a pulse from the mater timer every frame

For most periodic tasks, 60 times a second. That doesn’t mean you need to run your task 60 times a second – we’ll also manage setting the frequency of the task in this section.

If you need to test it on your system, check out my article on the animation timer’s speed, which goes into how you can test it yourself.

So, we’ll approach this in two steps:

  1. Creating an AnimationTimer and setting the executable code
  2. Setting the frequency of the AnimationTimer

The AnimationTimer uses the animation pulse JavaFX provides as a timing mechanism to shift code onto the UI thread.

This is a little bit of a simplification but the animation pulse does invoke your code on the application thread.

1. Creating an AnimationTimer and setting the executable code

The AnimationTimer is an abstract class with one abstract method. So, to create an AnimationTimer, we override that abstract method handle(). This is the method that will get called every frame, so any executable code you want to run goes here.

AnimationTimer timer = new AnimationTimer() {
    @Override
    public void handle(long now) {
        //Set executable code here
    }
};
timer.start();

Warning! You can start the animation timer easily enough by invoking start(), however the stop() method is a little misleading. If you call stop(), the animation timer will stop listening for the pulse, and therefore stop executing your code. However, the timestamps don’t stop!

So, when you start your timer again, if you’re using the timestamps to calculate anything, it’ll be like your animation never stopped!

With a little modification, you can extend the AnimationTimer to add in some proper timing functionality.

2. Setting the frequency of the AnimationTimer

To set the frequency of the AnimationTimer, we’ll need to create code that checks each frame whether enough time’s passed to fire our action again.

The easiest way to do that is to keep track of the timestamp of the last frame, and then calculate whether enough time’s passed each frame.

import javafx.animation.AnimationTimer;
public abstract class PeriodicPulse extends AnimationTimer {
    long nanosBetweenPulses;
    long lastPulseTimeStamp;
    public PeriodicPulse(double secondsBetweenPulses){
        //if negative time, default to 0.5 seconds.
        if(secondsBetweenPulses < 0) secondsBetweenPulses = 500000L;
        //convert seconds to nanos;
        nanosBetweenPulses = (long) (secondsBetweenPulses * 1000000000L);
    }
    @Override
    public void handle(long now) {
        //calculate time since last pulse in nanoseconds
        long nanosSinceLastPulse = now - lastPulseTimeStamp;
        //work out whether to fire another pulse
        if(nanosSinceLastPulse > nanosBetweenPulses){
            //reset timestamp
            lastPulseTimeStamp = now;
            //execute user's code
            run();
        }
    }
    abstract void run();
}

Note two things:

  • The constructor of the PeriodicPulse takes a double value which corresponds to the delay between events in seconds.
  • While the PeriodicPulse consumes the handle() method of the AnimationTimer, it also provides another abstract method run(), which it periodically calls at the interval fixed by the user.

Obviously, you could expand this code to allow users to change the periodicity, but I’ll trust you to add that in later. So, to use this code, we simply need to:

  • Create a PeriodicPulse, specifying the time between pulses, and
  • Define our executable code when we override the new abstract method run();
public class Ambulance extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Circle siren = new Circle(100, Color.BLUE);

        PeriodicPulse pulse = new PeriodicPulse(1) {
            int count = 0;
            @Override
            public void tick() {
                if(count++ % 2 ==0){
                    siren.setFill(Color.RED);
                } else {
                    siren.setFill(Color.BLUE);
                }
            }
        };
        pulse.start();
        primaryStage.setTitle("AnimationTimer Pulse Example");
        primaryStage.setScene(new Scene(new StackPane(siren), 200, 200));
        primaryStage.show();
    }
}

Result:

If you need more convenient control over the timing of your pulses, and you don’t fancy hard-coding the checks, you can use the Timeline. It’s a JavaFX object designed for animations, but it also has the ability to fire events periodically, which is perfect for us.

2. Timelines and Event Handlers

The Timeline class is designed to interpolate values between key frames – that’s actually really convenient if you want to fire an event that is going to depend on an animated value.

A Timeline will run from time zero until the last KeyFrame, and by default it will end immediately after the last frame is called.

A simple timeline with two key frames
This TImeline is exactly 200 milliseconds long. As soon as the last KeyFrame is reached, the animation ends!

We can convert this into a periodic task in to steps:

  1. Specifying it should repeat indefinitely
  2. Add KeyFrames with an EventHandler, which will fire every time the Timeline reaches a KeyFrame.

If we set two KeyFrame objects at 500 and 1000 ms, the Timeline will last exactly 1000ms. It will move through the animation, firing events at each KeyFrame, and then loop at the end.

In this case, both events will fire once per second, 0.5 seconds apart. Let’s set it up.

1. Specifying a Timeline should repeat indefinitely

The simplest Timeline can be created as a completely empty animation – without any key frames at all.

Timeline timeline = new Timeline();

To define a repeating animation, all you have to do is set the cycle count to the utility value of Animation.INDEFINITE.

timeline.setCycleCount(Animation.INDEFINITE); // loop forever

Now we have a Timeline (of length zero), which will cycle indefinitely. To set the length of the animation (and therefore the frequency of the periodic task, we can add KeyFrames – each with their own events.

2. Add KeyFrames with an EventHandler, which will fire every time the animation loops

If you’re aiming for concise code, you can add key frames to your Timeline in the constructor call when you create it. For now, I’ll create key frames as stand-alone objects, we can always add them later!

KeyFrame 1 – rotate a rectangle (0.5 s)
KeyFrame rotate = new KeyFrame(
        Duration.seconds(0.5),
        event -> {
            rectangle.setRotate(90);
        }
);
KeyFrame 2 – rotate rectangle back again! (1 s)
KeyFrame rotateBack = new KeyFrame(
        Duration.seconds(1.0),
        event -> {
            rectangle.setRotate(0);
        }
);

By using two key frames, we get the same periodicity (delay between executing), but they’ll also be off-set with respect to each other by the same amount each time.

Add Keyframes to an existing Timeline
timeline.getKeyFrames().addAll(rotate, rotateBack)
Full Code:
public class Ambulance extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Rectangle rectangle = new Rectangle(100, 50, Color.BLUE);
        KeyFrame rotate = new KeyFrame(
                Duration.seconds(0.5),
                event -> {
                    rectangle.setRotate(90);
                }
        );
        KeyFrame rotateBack = new KeyFrame(
                Duration.seconds(1.0),
                event -> {
                    rectangle.setRotate(0);
                }
        );
        Timeline timeline = new Timeline(
                rotate, rotateBack
        );
        timeline.setCycleCount(Animation.INDEFINITE);
        timeline.play();
        primaryStage.setTitle("Timeline Pulse Example");
        primaryStage.setScene(new Scene(new StackPane(rectangle), 200, 200));
        primaryStage.show();
    }
}

Result:

3. Using JavaFX’s Task class with a ScheduledService

For more complicated chunks of code, it can be important to do one of two things when you’re running a background task periodically:

  • Track the progress of the task
  • Return a value at the end of the process, which can also be used to update the UI.

What is a Task?

A Task object is a runnable object that provides additional functionality to:

  • Return a value from the asynchronous activity
  • Update the progress of the activity as it occurs.
  • Set additional executable code to be invoked on either successful completion of the task, or failure.
Through listening or binding, any changes to a Task’s Progress property can also result in changes to the UI.

When to use a Task with a scheduler

The JavaFX Task should be used for longer, more complex code blocks that need to be carried out asynchronously.

Task progress is exposed as a property to enable property binding. This makes it perfect for use cases involving updating the user about the task’s progress while it’s running.

Use cases where you need to run some extra code on completion of the asynchronous code are also be supported. Conveniently, the functionality is backed by EventHandlers, meaning this extra code is executed on the Application thread.

Finally, Tasks also extend the Future class, meaning use cases involving asynchronous tasks that must return values are supported through the task.get() method.

How to use a ScheduledService with a Task

Let’s write a quick example to demonstrate all the basic features of the ScheduledService and Task.

  1. Create a Task to complete a function
  2. Schedule the Task to repeat every 5 seconds.

First, we’ll create a Task that returns a list of String objects. In my head, it’s a list of book names from a database, but whatever it is, it’s a List. We specify this by parameterising the Task as we create it. It’s going to be a Task<List<String>>.

Inside the executable code, we’ll simulate loading some Strings from a database by sleeping the thread instead of using a live connection. We can set the executable code by overriding call(), which is executed when we start the task. Notice that call returns List<String>.

1. Create a Task to complete a function

We’re creating an anonymous class, so we’ll define an internal method getFromDatabase() which will simulate retrieving items from a database, but in reality we’ll simulate the delay between requesting and getting the data with Thread.sleep(1000).

Task<List<String>> pollDatabaseTask = new Task<>() {
    List<String> bookNames = new ArrayList<>();
    @Override
    public List<String> call() {
        final int toLoad = 10;
        for (int i = 1; i <= toLoad; i++) {
            bookNames.add(getFromDatabase(i + 1));
            updateProgress(i, toLoad);
        }
        return bookNames;
    }
    //Simulate database delay
    private String getFromDatabase(int bookNumber) {
        try {
            Thread.sleep(225);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Book Number: " + bookNumber;
    }
};
Binding the Progress

We’ll be loading 10 items, so every time we load a String, we’ll update the task’s progress using the built-in method updateProgress(). We’ll take advantage of the task’s progress property by binding it to a ProgressBar, which we’ll load into our scene.

ProgressBar progressBar = new ProgressBar();
progressBar.progressProperty().bind(pollDatabaseTask.progressProperty());
rootNode.getChildren().add(progressBar);
1. Schedule the Task to repeat every 5 seconds.

To execute our Task, we’ll create a ScheduledService with which to run the task. To create a ScheduledService, we will need to overwrite the createTask() method (which is abstract).

ProgressBar progressBar = new ProgressBar();
ScheduledService<List<String>> scheduledService = new ScheduledService<>() {
    @Override
    protected Task<List<String>> createTask() {
        Task task = new Task<>() {
            final List<String> bookNames = new ArrayList<>();
            @Override
            public List<String> call() {
                //code defined above
            }
            //Simulate database delay
            private String getFromDatabase(int bookNumber) {
                //code deined above
            }
        };
        progressBar.progressProperty().bind(task.progressProperty());
        return task;
    }
};

Note the binding inside the createTask() method: I’ve found if you try to define the task outside the ScheduledService, you run into event-firing related errors.

What we’re expecting here is a progress bar that takes about 2 seconds to fill up, repeating every five seconds.

Full Code:

public class TimerTest extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Label taskLabel = new Label();
        ProgressBar progressBar = new ProgressBar();
        ScheduledService<List<String>> scheduledService = new ScheduledService<>() {
            @Override
            protected Task<List<String>> createTask() {
                Task task = new Task<>() {
                    final List<String> bookNames = new ArrayList<>();
                    @Override
                    public List<String> call() {
                        final int toLoad = 10;
                        for (int i = 1; i <= toLoad; i++) {
                            bookNames.add(getFromDatabase(i + 1));
                            updateProgress(i, toLoad);
                        }
                        System.out.println("Got all books!");;
                        return bookNames;
                    }
                    //Simulate database delay
                    private String getFromDatabase(int bookNumber) {
                        try {
                            Thread.sleep(225);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return "Book Number: " + bookNumber;
                    }
                };
                task.setOnSucceeded(workerStateEvent -> taskLabel.setText("Waiting..."));
                task.setOnRunning(workerStateEvent -> taskLabel.setText("Task Running"));
                progressBar.progressProperty().bind(task.progressProperty());
                return task;
            }
        };
        VBox vBox = new VBox(progressBar, taskLabel);
        vBox.setPrefWidth(300);
        vBox.setPrefHeight(250);
        vBox.setAlignment(Pos.CENTER);
        scheduledService.setPeriod(Duration.millis(5000));
        scheduledService.start();
        primaryStage.setScene(new Scene(vBox));
        primaryStage.setTitle("Task Scheduling Example");
        primaryStage.show();
    }
}

This task should run for about seconds, with a progress bar that periodically increases in completeness.

It’s also worth noting I’ve added a Label that gets updated based on the Task status, as well as a progress bar to track progress. That’s because the Task can fire events on scheduled, start, complete, fail or are cancelled.

Task objects can fire events when they are scheduled, start,  complete, fail or are cancelled.

Events are one of the most powerful elements of JavaFX. If you’re interested in making the most out of them, check out my complete guide to JavaFX Events. It goes into a lot of details about how to use them, as well as how to deploy them effectively.

Updating the UI from within the Task

The Task object is designed to outsource work away from the JavaFX Application thread. So, if you try to update the UI directly from the Task‘s call() method, you’ll be greeted with an IllegalStateException: Not on FX application thread exception.

It’s not usually needed, but if you absolutely need to, you can manually fire changes on the UI by wrapping your UI-update in a Platform.runLater() call.

Platform.runLater(() -> {
    taskLabel.setText("Manually updating from Task");
});

Usually, a better way to do this would be to add a listener on the progress property. This way, you can fire it using an event, which will be executed on the Application Thread. For now, here’s the result of our scheduled task.

Result:

Sometimes you want to conduct a background task that just doesn’t need to update the user-interface. That can be keeping synchronised with a server, or checking local files for changes. In either case, it’s often more efficient to run these tasks off the Application Thread.

Swamping the application thread can lead to a laggy UI, so it’s a really good idea to run whatever tasks you can in the background. Both the AnimationTimer and Timeline setups execute their code on the UI thread, so if you’re doing anything intensive, you may see the UI lagging.

The Task set-up does outsource your code so it doesn’t run on the UI thread. That being said, it also inflates properties, which might be undesirable if you have memory-constraints. If you’re in that situation, it may be worth offloading from JavaFX altogether.

Of course, critical UI updates can be wrapped in Platform.runLater(), just as in the Task example above.

Running background tasks off the Application Thread

The first of these non-JavaFX options is the Timer/TimerTask set-up, which can schedule tasks on a single thread (no concurrency). For more intensive groups of background tasks, check out the ScheduledExecutorService below, which multi-threads as well as schedules your tasks.

A Timer with a registered TimerTask

The timing mechanism for the Timer/TimerTask set up doesn’t require any features of JavaFX, in fact, it’s all taken straight from the Java concurrency package.

Here, we’ll create a scheduled background task in two steps:

  1. Create a TimerTask that’s going to complete our action
  2. Schedule that TimerTask with a Timer

In this case we’re going to print something to the console, which is possibly the most underwhelming use of background scheduling. But don’t worry, I trust you to come up with something more inventive for you app.

1. Create a TimerTask to complete an action

The TimerTask itself will create the mechanism for firing an action once it’s scheduled. Similar to the AnimationTimer, the TimerTask object has a single abstract method run(), which is where we’ll put our executable code.

TimerTask task = new TimerTask() {
    @Override
    public void run() {
        System.out.println("Checking local files...");
    }
};

Again, I’m just going to print something to the console, but for the love of God, feel free to do something useful with that executable code block.

Here’s a few things that are worth noting though:

  1. The TimerTask can’t return any values
  2. The TimerTask code is going to be executed off the JavaFX Application Thread, so it can’t natively be used to update the UI.

As a reminder, if you do want to update the UI from a TimerTask, you’ll need to wrap your update in Platform.runLater():

TimerTask task = new TimerTask() {
    @Override
    public void run() {
        System.out.println("Checking local files...");
        Platform.runLater(() -> {
                //update UI thread from here.
        });
    }
};

A TimerTask can be run itself by invoking task.run(), but we’ll need to use a Timer object if we want to repeatedly schedule our code.

2. Schedule that TimerTask with a Timer at a fixed rate

To schedule a TimerTask to execute periodically, we need create a Timer object, and associate the TimerTask with it.

It’s actually ridiculously simple to schedule a Timer, and it can be done in a single line of code. To see how you can customise it even more, check out the documentation here.

Timer t = new Timer();
t.scheduleAtFixedRate(
        task ,
        0,      //delay before first execution
        1000L); //time between executions

Again, one important aspect here is to remember that the time between executions should be specified in milliseconds. If you’ve been using the AnimationTimer, you’ll be used to nanoseconds, so just watch out here.

The overall effect in this case is a little underwhelming, because the Timer and TimerTask shouldn’t be used to update the user interface.

Result:

> Stopping execution

To stop the Timer, you’ll need to invoke timer.cancel(), which will stop the timer from launching new tasks. Any TimerTask that’s already started will continue until the task is complete, but won’t execute again.

There’s no way to stop execution of a TimerTask, unless you define code within the run() method that allows you to prematurely exit the task. Invoking cancel() on a TimerTask will prevent it from running again, but won’t stop it mid-run.

Like the AnimationTimer and Timeline objects, the Timer deals completely in fire-and-forget tasks. If you need something that will keep track of the success or failure of the task, you’ll need to use the ScheduledExecutorService below.

A ScheduledExecutorService and an associated Runnable

Finally, if your aim is to manage multiple long-running tasks in the background, your best choice is the ScheduledExecutorService object, which provides the timing mechanism to schedule a task as well as multi-threading to juggle them. The task itself will be run through a Runnable object.

Again, we’ll do this in two steps:

  1. Create a Runnable.
  2. Schedule the Runnable with a ScheduledExecutorService

1. Create a Runnable

A Runnable can be as simple or as complex as required, but in this case we’ll define it as a lambda expression:

Runnable task = () -> System.out.println("Checking Server");

If you need something more complex, you can define it as a lambda statement:

Runnable task = () -> {
    System.out.println("Checking Server");
    //Other multi-line code instructions
}

Either way, you can instruct the Runnable to execute its code by invoking task.run(), or by loading it into a Thread. That would execute it once, but it’s not what we want to do here. Instead, we’ll schedule the Runnable using a ScheduledExecutorService.

2. Schedule the Runnable with a ScheduledExecutorService

Scheduling a Runnable is almost as simple as creating it – one line of code is needed to create a ScheduledExecutorService, and one more line is needed to schedule the Runnable.

Especially important is the input to Executors.newScheduledThreadPool(), which defines the number of threads the executor service should

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
executorService.scheduleAtFixedRate(task, 0 ,1, TimeUnit.SECONDS);

The scheduleAtFixedRate() method takes four parameters:

  • The Runnable to schedule
  • The amount of time before execution (units in variable 4)
  • The amount of time between executions (units in variable 4)
  • The time unit that the method should use to evaluate the delay and period variables (2 and 3).

Because multi-threading is the goal here, you’ll want to keep a reference to the ScheduledExecutorService. That way you can schedule multiple background tasks, all running autonomously over multiple threads without any need for upkeep from you

> Stopping execution

To stop the task from running, you’ll need to invoke executorService.shutdown(), which will shut down the executor service after running all scheduled tasks. Alternatively shutdownNow() will stop everything immediately.

Conclusions

There are a lot of ways to execute tasks periodically in both Java and JavaFX. In this article I’ve tried to outline five that give developers the opportunity to access varying degrees of efficiency and convenience.

Running simple periodic tasks on the JavaFX Application Thread can be achieved in many ways. Three of the easiest are using an AnimationTimer, Timeline and ScheduledService. These run based on JavaFX’s animation and concurrency packages, which both contain timing switches to help with scheduling.

Conveniently, Java also has ways to execute tasks periodically. For lower-intensity background activity, the TimerTask and Timer setup allows you to periodically execute (simple) tasks, without multi-threading. For more labour intensive set-ups, the ScheduledExecutorService gives you the option to dip into multi-thread pools, and gives you a lot more convenience in set up.