For the past couple of years the industry has continued to follow Moore’s Law by shifting from CPU clock speed to increasing the number of cores and threads per core. Even cell phones are getting multiple cores these days! Taking advantage of all these cores and threads is one of the hallmarks of modern GUI platforms. But all this concurrency brings a multitude of problems to the application developer, not least of which is that writing multithreaded applications is hard!
In designing JavaFX 2.0, we of course needed to address both how the scene graph would behave in the presence of multiple threads, and how developers could effectively do work in background threads and keep the UI responsive. In short, the JavaFX scene graph, like all other mainstream GUI toolkits, is not thread-safe and must be accessed and manipulated from the UI thread (call the FX Application thread). Swing and AWT had the same basic policy (only work with Swing or AWT from the Event Dispatching Thread), as did SWT (only interact with SWT resources and components from the thread that owns them), as do all other major toolkits (JavaScript / HTML included).
The most common problem with this design is that developers who do not do work on background threads invariably create unresponsive applications, since this long lived (potentially blocking) code happens on the same thread that processes user events. That is, while your long lived operation is running, no mouse or key events are being processed, which leads to an application that appears to “hang”.
Further, actually writing well behaved background workers is difficult and error prone. Even if you create a Runnable and create a Thread and do your long-lived work in that background thread, at some point you need to communicate back to the UI, either with the result of the long-lived computation, or by communicating to a ProgressIndicator of some kind what the progress of this long-lived operation is. This is error prone, because you must be sure to communicate with the UI by putting events back onto the event queue (using Platform.runLater, the equivalent of Swing’s invokeLater).
Note: This article is a sneak peek at a new API which is coming in the next couple of weeks, but is not currently available in the Beta builds! There is a deprecated Task class in the beta builds which will be removed and replaced with the one detailed here.
Suppose we have a simple background thread which just counts from 0 to 1 million. Suppose I have a single ProgressBar, and that I need to update the progress of this ProgressBar as the counter runs. A naive implementation might look like this:
final ProgressBar bar = new ProgressBar(); new Thread(new Runnable() { @Override public void run() { for (int i=1; i<=1000000; i++) { final int counter = i; Platform.runLater(new Runnable() { @Override public void run() { bar.setProgress(counter/1000000.0); } }); } } }).start();
This is a hideous hunk of code, a crime against nature (and programming in general). First, you’ll lose brain cells just looking at this double nesting of Runnables. Second, it is going to swamp the event queue with little Runnables — a million of them in fact. Clearly, we needed some API to make it easier to write background workers which then communicate back with the UI.
Java comes with a very complete set of concurrency libraries in the java.util.concurrent package. We wanted to leverage what was already defined in Java, but we needed to extend these APIs to take into account the FX Application thread and the constraints that GUI programmers are under. The javafx.concurrent package contains three core files: Worker, Task, and Service.
Before diving into the rather verbose description (taken from the proposed javadocs) for Worker, Task, and Service I wanted to cut to the chase and show some examples. The first key thing to mention, is that Worker is an interface that is implemented by both Task and Service, and which adds the sort of convenience API necessary for a background worker that is useful for communicating back with a UI. Second, Task extends from java.util.concurrent.FutureTask. This means that a Task can very cleanly fit into the concurrent libraries. As you may know, FutureTask implements Runnable, and can be passed to an Executor’s execute() method.
So real quick, here is the same example as above, but it suffers from none of the flaws exhibited in the naive implementation.
Task task = new Task<Void>() { @Override public Void run() { static final int max = 1000000; for (int i=1; i<=max; i++) { updateProgress(i, max); } return null; } }; ProgressBar bar = new ProgressBar(); bar.progressProperty().bind(task.progressProperty()); new Thread(task).start();
In this example, I first create my Task. The task implementation just does its work, invoking the protected updateProgress
method defined on Task, which ends up updating progress, totalWork, and workDone properties on the Task. I then create my ProgressBar and bind its progress property with the progress property of the Task. Then, since Task is a Runnable, I can just create a new Thread passing it the Task and then start the Thread.
Alternatively, I could create an Executor or ExecutorService (such as a ThreadPoolExecutorService) and execute
the task using the ExecutorService.
Edit July 11, 2011: I have updated the API slightly since this post was originally written, and I’ve updated the post to reflect the current names. In particular, the “progress” property is now a value between 0 and 1 (or -1), matching the “progress” property on ProgressIndicator and other parts of the platform. “workDone” and “totalWork” are used to indicate the total units of work to do (such as bytes to be downloaded) and the total units of work that have been done (such as the bytes that have been downloaded). I’m not totally jazzed by the names, but felt it was important for “progress” to mean the same thing on Worker and ProgressIndicator.
Below are some further descriptions taken from the javadocs.
Worker
A Worker is an object which performs some work in one or more background threads, and who’s state is observable and available to JavaFX applications and is usable from the main JavaFX Application thread. This interface is primarily implemented by both Task and Service, providing a common API among both classes which makes it easier for libraries and frameworks to write user interfaces with observable workers.
A Worker may, or may not be reusable, depending on the implementation. A Task, for example, is not reusable while a @link Service is.
A Worker has a well defined life cycle. Every Worker begins in the READY state. When the Worker has been scheduled for work (for example, when a Service’s start() method is called), it is transitioned to SCHEDULED. Even Workers which are not technically scheduled, but started immediately (such as with Task#run()) will transition through SCHEDULED on its way to the RUNNING state.
When the Worker is actually performing its work, the state will have been transitioned to RUNNING. If the Worker completes normally, it will end in the SUCCEEDED state, and the result of the Worker will be set as the value
property. If however an Exception occurs during the execution of the Worker, then the state will be set to FAILED and the exception
property will be set to the Exception which occurred.
At any time prior to the conclusion of the Worker (that is, if the state is not already SUCCEEDED or FAILED) the developer may invoke the Worker#cancel() method. If called, the Worker will cease execution (if possible, including use of Thread.interrupt) and the state changed to CANCELLED.
The only valid beginning state for a Worker is READY, and the valid ending states are CANCELLED, SUCCEEDED, and FAILED. The running
property is set to true when the state is either SCHEDULED or RUNNING.
The Worker’s progress can be monitored via three different properties, workDone
, totalWork
, and progress
. These properties are set by the actual implementation of the Worker interface, but can be observed by anybody. The workDone
is a number between -1 (meaning indeterminate progress) and totalWork
, inclusive. When workDone == totalWork
the progress
will be 100% (or 1). totalWork
will be a number between -1 and Long.MAX_VALUE, inclusive. The progress will be either -1 (meaning indeterminate), or a value between 0 and 1, inclusive, representing 0% through 100%.
A Worker which is in the READY or SCHEDULED states will always have workDone
and progress
set to -1. A Worker which is in the SUCCEEDED state will always have workDone == totalWork
and progress == 1 or -1
. In any other state, the values for these properties may be any value in their respective valid ranges.
Task
A fully observable implementation of a FutureTask. Tasks exposes additional state and observable properties useful for programming asynchronous tasks in JavaFX, as defined in the Worker interface. An implementation of Task must override the Task#call() method. This method is invoked on the background thread. Any state which is used in this method must be safe to read and write from a background thread. For example, manipulating a live scene graph from this method is unsafe and will result in runtime exceptions.
Tasks are flexibly and extremely useful for the encapsulation of work. Because Service is designed to execute a Task, any Tasks defined by the application or library code can easily be used with a Service. Likewise, since Task extends from FutureTask, it is very easy and natural to use a Task with the java concurrency java.util.concurrent.Executor API. Finally, since a Task is Runnable, you can also call it directly (by invoking the Task#run() method) from another background thread. This allows for composition of work.
Although java.util.concurrent.ExecutorService defines several methods which take a Runnable, you should generally limit yourself to using the execute
method inherited from java.util.concurrent.Executor.
As with FutureTask, a Task is a one-shot class and cannot be reused. See Service for a reusable Worker.
Because the Task is designed for use with JavaFX GUI applications, it ensures that every change to the public properites, as well as change notifications for state, errors, and for event handlers, all occur on the main JavaFX application thread. Accessing these properties from a background thread will result in runtime exceptions being raised.
Service
A Service is a non-visual component encapsulating the information required to perform some work on one or more background threads. As part of the JavaFX UI library, the Service knows about the JavaFX Application thread and is designed to alieviate the application developer from the burden of manging multithreaded code that interacts with the user interface. As such, all of the methods and state on the Service are intended to be invoked exclusively from the JavaFX Application thread.
Service implements {@link Worker}. As such, you can observe the state of the background operation and optionally cancel it. Service is a reusable Worker, meaning that it can be reset and restarted. Due to this, a Service can be constructed declarativley and restarted on demand.
If an java.util.concurrent.Executor is specified on the Service, then it will be used to actually execute the background worker. Otherwise, a daemon thread will be created and executed. If you wish to create non-daemon threads, then specify a custom Executor (for example, you could use a ThreadPoolExecutor).
Because a Service is intended to simplify declarative use cases, subclasses should expose as properties the input parameters to the work to be done. For example, suppose I wanted to write a Service which read the first line from any URL and returned it as a String. Such a Service might be defined, such that it had a single property, url
. It might be implemented as:
public class FirstLineService extends Service { private StringProperty url = new StringProperty(); public final void setUrl(String value) { url.set(value); } public final String getUrl() { return url.get(); } public final StringProperty urlProperty() { return url; } protected Task createTask() { final String _url = getUrl(); return new Task<InputStream>() { protected String call() { URL u = new URL(_url); BufferedReader in = new BufferedReader( new InputStreamReader(u.openStream())); String result = in.readLine(); in.close(); return result; } } } }
Conclusion
We anticipate that libraries of Tasks, both specialized for your specific application and also general libraries of Tasks will be developed over time that perform common operations such as downloading files, performing HTTP form submits, copying files, uploading files, sorting, doing statistical analysis, and so forth. These reusable bodies of code can then be combined together, used with thread pools or other rich executor services, and used with Services.
Let us know what you think!
Cool article, tnx!
But when I try work with this stuff – problems immediately appear!
1.
Task is labeled “deprecated”.
2.
Moreover, Task doesn’t contain run() method, only execute().
3.
Current javafx documentation doesn’t know about Worker/Service at all. Maybe I searched it in wrong place?^(
4.
“new Thread(task).start()”
“no suitable constructor found for Thread(javafx.async.Task)” :(((
Shame on me, it is wrong Task! 🙂
Is javafx.concurrent available for now? I can’t reach it from Netbeans and JavaFx SDK b32
Hi Anatol, sorry for the confusion! While editing the blog post I accidentally removed one vital bit of information, which is that this change will show up in I think b34 (give it a couple of weeks). This is all cutting edge stuff. The reason Task was deprecated in previous builds was because we were planning on making the changes detailed in this post, and wanted to make sure people were aware of this.
Excellent information! It will be extremely useful package!!!
It is good news that such work is done, and will definitly help to keep all those cores busy 🙂
However, from a Clojure point-of-view the proposed solution is unfortunate. In some areas of the JFX API I saw the same challenge: creating an anon class and calling protected methods. The low-level binding API requires the same.
In an ideal API a class would introduce many methods itself (mostly getters and setters). It only would offer (public) fields. Nearly all methods are introduced by implementing interfaces (yes, this would lead to many interfaces that include methods which will be implemented by only one class).
I understand that this will not be possible, but it would still be useful to offer some alternative approaches so that other JVM languages also could use JFX, without requiring to write Java code. When I want to write a Task, then I would just like to provide a function object (the implementation), and be done with it. JFX should not have Clojure as a dependency, and so overloading it and accepting a Clojure function as argument for a method call is not the right way.
One Way could be to offer static methods that take an object that implements a specific interface. There could be a interface TaskITF that provides the necessary methods. One could then call Task.createTask(TaskITF t). All without having the need to subclass or to call protected methods, or anything from superclasses.
Great article indeed!
Ps: i think there ‘s a typo in the code example using Task. Static should be removed from the line: static final int max = 1000000;
great info! thanks for the explanation. It is really important to have that kind of feedback from you guys.
at the risk of changing the subject: do you plan to include FXML in javafx 2.0 GA…and post a similar post concerning FXML?
Yep, it should be available within the next few weeks to play with (about the same time as this Task stuff, actually).
great news! Looking forward to it
Oh well, a pity, but I’m sure there are sensible reasons for it. I’d got my hopes up. I was hoping JavaFX 2.0 would take the step of being thread-safe. Tasks still seem predicated on the idea that off-UI-thread tasks are long and few. As cores increase, it seems to me that off-thread tasks in future might be short and many. So the Task would increasingly be boilerplate littering code.
I had quietly hoped JavaFX 2.0 would be designed to be thread-safe, and that the default would be that the Application does not sit on the event dispatch thread but entirely in one or more Worker threads. At first glance, closures/lambdas seemed to be an easy way to make that possible. Internally to the API, methods would either executeAndWait if they are not called from the EDT, or run directly if they are.
But then it’s easy to think “Wouldn’t it be nice if…” when I don’t have to write the code or discover what the unintended ramifications for the API would be!
Actually, what we want to do is to “fail-fast” much like the Collection’s framework or WPF or SWT, such that if you attempt to use the scene graph from the wrong thread we throw an unchecked exception, as opposed to Swing which would just carry on (and perhaps deadlock, or perhaps silently corrupt data, or perhaps just work). Truly thread-safe GUI toolkits are definitely still a research problem — none of the major toolkits attempt it.
Richard – this is wonderful stuff and a welcome change from the JavaTaskBase/RunnableFuture pairs we use so heavily in our SoMa app. I’m eager to start experimenting with Worker/Task/Service.
Please forgive me for using your threading post as a segue, but my principal concern for Presidio and beyond is not so much the ‘how’ of worker threading, but the ‘what’ – as in what the background heavy lifting actually is.
Our SoMa app frequently creates RunnableFutures that go to work on BufferedImages of type TYPE_USHORT_GRAY, and are suffused with BufferedImage, Raster, WritableRaster, getPixel, setPixel and ImageIO.
Through trial and error, we discovered that, after background image processing,we can downsample and use getGraphicsConfiguration().createCompatibleImage() to get a decent visual representation into the scene graph via SwingUtils.toFXImage() and ImageView.
I haven’t tried it yet but it seems that, in Presidio, we ought to be able to encode a BufferedImage to a byte array and use the Image constructor that takes a java.io.InputStream to get it into the scene graph.
However, from the roadmap and various 2.0 posts, I understand that java.awt (presumably including java.awt.image) is antithetical to Prism. Are you able to share your plans for a successor to the BufferedImage stack?
Otherwise, Presidio is shaping up to be really terrific and please know that some of us out here are great admirers of your work.
Rick
Hi Rick,
Actually with FX / Swing interop (ability to embed FX in Swing), we still use Prism. It runs side-by-side with AWT, so it would seem that your use case or approach here should work. I could see some threading issues potentially cropping up, but I don’t see anything that says this absolutely couldn’t work.
javafx.async.Task is deprecated in the latest JavaFX 2.0 build 34. I take it that this post is out of date? What is the updated equivalent?
This new API described in this post made it into b35, so in the next public drop you’ll see it.
Great, I got build 36 installed and I see the non-deprecated javafx.concurrent stuff.
First, there is no JavaDoc for javafx.concurrent. I see JavaDoc for all the other JavaFX 2.0 packages in .netbeans/7.0/lib/docs/api/javafx, but javafx concurrent is not there.
Secondly, how do I kick off a background task from the GUI thread and implement a completion callback that runs in the GUI thread? In FX 1.2.x, this was pretty straightforward with JavaTaskBase. I’ve reread this post in it’s entirety and I don’t see how to do this with the new package.
(BTW, sorry for my first comment. I see you addressed that issue in the main post and several times in the comments)
Hi Richard, this is a really great start for us. I realise this post is getting a tad old now but this still seems to be the only real example of using the new Service stuff in JFX2.
It is a bit of a teaser though. It would be great to see an actual example of how to use this API to do the common UI/background workflow, namely:
1. Get some stuff from the screen (i.e. details enetered in a form)
2. Do a slow background task using the details entered
3. Update the screen with the results from the background task
There are many different properties and options, so seeing how it is *intended* to be used for this common scenario would be extremely useful for me and I imagine many others.
Cheers,
zonski
Hi Richard
Task priceUpdateTask = new Task() {
@Override public Void run() {
while (true) {
BigDecimal price = getFinancialPriceFromSomewhere(…)
updateProgress( price );
}
return null;
}
};
What happens if I have a “task”, which is not predictable and may not exit or runs forever? How can one just update the price using a decimal type e.g. float, double, BigDecimal?
Currently the only way I found was Platform.runLater() see my talk Progressive JavaFX 2.0 and code
Yep, using Platform.runLater() is the best solution I would say.
Any chance the Service class will get an onFinished event we can listen in on or a finished callback of some kind? That will give us extra flexibility beyond the runLater option.
Here is the issue: http://javafx-jira.kenai.com/browse/RT-17449, please vote for it if you want it! I think this is a fine thing, earlier versions of the class did have these events but I pulled them because, as an API designer, “less is more” until customers make specific requests. That is, it is sometimes hard to know up front exactly what convenience API would make somebodies life a lot easier and what convenience API is just “bloat”, so I decided to start off with a smaller API and wait for the shouting :-). I personally like the idea of having events for these things.
Ah, good to know. My initial observations with FX 2.0 have definitely discovered this ‘less is more’ approach, but often creates more code on the API user’s end, a lot of gray hairs and sometimes dead-ends. But good work anyhow, I’ll be sure to request more things we find missing.
Yes, definitely request more things! One of our main goals for the next year is “fit and finish”, so knowing what areas cause pain is very important.
Hi All, Looks old thread but very informative.I am stuck here. Looks simple but its tricky.
I have a progressbar which gets progressed at different places in doInBackgroud() method. Here in doInBackground i am doing something like this. (Consider it as sequential.)
Task.setTaskProgress(60);
MessageResponse response = getHttpURLConnectionResponse(connection);
Task.setTaskProgress(100);
Here it waits for the response for quite a long time and progressbar looks hung at 60%. and after getting the response it jumps to 100%. So my question is how can i slow increment the progress bar from 60% to 100% . (fake update till i get the response).?
The usual trick is to switch to indeterminate while waiting for some “indeterminate” task! So right before you attempt to make the connection, set the task progress to indeterminate, and then after the connection is made you can either finish the task or if you are parsing a file you can update progress based on the number of bytes parsed or whatnot.
Richard thanks a lot for the reply.
The problem that I’m facing is. Wherever I use the above reponse statement program waits till the response and then continues execution. I wanted to show some progress during that waiting time.
Your help is greatly appreciated.
@Pavan, I don’t know what you are asking. I assume you are executing the blocking call on the background thread and not the FX thread. The normal UI interaction is to use an indeterminate progress visual when you are doing something that could last some arbitrary amount of time, and a determinate progress visual when you are some determined amount through some task (such as downloading bytes).
Hi Richard, thanks for the article.
How does one schedule a Service to run after a certain amount of time? I see there is a SCHEDULED state, however this doesn’t seem to be exposed?
In a nutshell, is there an equivalent of ScheduledExecutorService.schedule()?
Good article! however I think using the Task example above to replace the inline Thread example to justify this statement “Second, it is going to swamp the event queue with little Runnables — a million of them in fact” is a little overlooked. Event if Task is used and GUI update is required then the Platform.runLater is still needed. The “A Task Which Modifies The Scene Graph” example in https://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html will justify.
Good, good, good! Very Useful. Thanks for this article, helped a lot.
thank you