JavaFX Timeline vs ScheduledExecutorService - java

In a JavaFX 8 project, you can use javafx.animation.Timeline like this:
Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(250),
actionEvent -> {
updateTemperature();
}
)
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
Or you can something very similar using a ScheduledExecutorService:
executorService.scheduleAtFixedRate(this::updateTemperature, 0, 250, TimeUnit.SECONDS);
Are there any "best practises" for using one over the other?

As with most UI toolkits, in JavaFX you must not access UI components that are part of the display from any thread other than the dedicated UI thread (the FX Application Thread in the case of JavaFX). Additionally, code that takes (or may take) time to run (e.g. has blocking calls, as with I/O or networking) should not be executed on the UI thread as it will make the UI unresponsive.
The two code snippets you posted are quite different with regard to threading. The ScheduledExecutor will execute updateTemperature() on a background thread (i.e. not the FX Application Thread). This is appropriate if updateTemperature() takes a long time to run; but it will likely throw an exception (or, worse, have the potential of leaving the UI in an inconsistent state) if it accesses the UI.
By contrast, the Timeline creates no new threads and executes updateTemperature() on the FX Application Thread. If updateTemperature() accesses the UI, it must be performed on this thread and this is a convenient way to do so. If it takes a long time to run (which I assume it doesn't, since you're calling it 4 times per second), it will have the effect of making the UI unresponsive.

Related

What is the difference between Timeline and Thread in java

The following two simple snippets do the same, print "Hello, world" each second. But what's the difference between them? When should I use a thread and when should I use Timeline. Does Timeline internally start a thread? if it doesn't, how the print gets executed each one second without blocking the main thread?
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), e -> System.out.println("Hello, world")));
timeline.setCycleCount(-1);
timeline.play();
new Thread(() -> {
while (true) {
System.out.println("Hello, world!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
And, In the second snippet, if I do Thread.sleep(some_volatile_variable_of_main_thread_that_changes_overtime), How can I achieve the same functionality using Timeline.
The Thread class is part of the standard Java API, and represents a background thread. When a Thread is started, the code in either its Runnable's run method, or its own run method, executes essentially in parallel to other running threads. This allows code that may take a long time to run to execute without delaying other code that can be run "at the same time". The cost to the programmer of using this is that great care must be taken if data is shared between different threads, to ensure it is read in a consistent state in any single thread, and that data is "live": that is, that changes made to data in one thread are actually observed in other threads.
By contrast, Timeline is part of the JavaFX framework, and in particular part of its animation API. When a JavaFX application is started, a thread called the FX Application Thread starts running. This thread runs in a loop and is responsible for rendering the UI and processing user events (among other things). The UI rendering occurs on a "pulse", which is (in the current version) targeted to occur 60 times per second. Because of the data synchronization issues alluded to above, all changes to the UI must be made on the FX Application Thread. Additionally, code on the FX Application thread must not be long-running (so it cannot pause with a sleep(), or read large data sets over IO), because it would block the thread from rendering the UI.
A Timeline works by having a set of KeyFrames, each of which specify a time (in the form of a Duration, measured since the timeline started) and an event handler and/or a KeyValue. On each pulse of the FX Application Thread, if a Timeline is running, the FX Application Thread loop will check if it is time to trigger any event handlers. For KeyValues, if the value is interpolatable (e.g. is numeric, or implements Interpolatable, it's value will be calculated by computing the time elapsed as a proportion of the time for the next KeyFrame.
Timelines are useful for simple animations (by, e.g., moving a node across a pane, by using KeyValues that specify it's layout position or translation coordinates, or similar), and also for performing a discrete set of UI updates at specific times (e.g. showing and hiding images in a "memory" game).
Consequently:
Code in event handlers for a KeyFrame attached to a Timeline may update the UI, since it is guaranteed to be executed on the FX Application Thread
KeyValues that are updated as part of a KeyFrame in a Timeline may be properties of UI elements that are displayed on the screen
Code in event handlers for KeyFrames must not block execution or perform long-running tasks
Trying to use a Timeline in a non-JavaFX application (i.e. one where the JavaFX runtime has not been started) will fail, because there will be no JavaFX Application Thread to execute the updates.
Conversely:
Code run on a background Thread must not update UI elements (or their properties). This is true both of JavaFX and Java Swing/AWT
Code run on a background thread may block or execute long-running tasks
Note that the java.util.Timer and it's associated TimerTask (which are part of the standard Java API) execute on a background thread created internally by the Timer. This means that, although the API of Timer and TimerTask look somewhat similar to Timeline, they must obey the rules of background threads (must not update the UI, etc).
In order to understand the difference, you need to think of two main questions:
When we use a separate Thread, can we update JavaFX UI controls from the same thread?
Given a WritableValue, how can we make a Thread change that value over time with a prespecified rate, start value, and end value?
From the Timeline documentation:
A Timeline can be used to define a free form animation of any
WritableValue, e.g. all JavaFX Properties. A Timeline, defined by one
or more KeyFrames, processes individual KeyFrame sequentially, in the
order specified by KeyFrame.time. The animated properties, defined as
key values in KeyFrame.values, are interpolated to/from the targeted
key values at the specified time of the KeyFrame to Timeline's initial
position, depends on Timeline's direction.
Example: Bouncing a ball 14 times (each bounce takes 3 seconds)
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(3),
new KeyValue(ball.layoutXProperty(), parentPane.getBoundsInLocal().getMaxX() - ball.getRadius())));
timeline.setCycleCount(14);
timeline.play();
In summary, Timeline was designed to support Animation by processing one or more KeyFrames sequentially in the JavaFX thread.
When should I use a thread and when should I use Timeline?
Timeline should be used for animations and updating writable UI values at a rate. Thread on the other hand should be used to run long background tasks (ExecutorService is always a better idea).
Does Timeline internally start a thread?
No, Timeline doesn't start new threads, it uses the JavaFX thread.
The last part is not exactly what a Timeline was designed for. If you have to change the duration, you need to reinitialize your Timeline or removing the old KeyFrame and adding a new one with the new duration.

Java FX modifying UI component state with/without using Platform.runLater

In java fx controller i have two version of the code that simply sets a text on a label when a button is pressed (this is just a sample, but any other ui modification can be considered)...
first version uses Platform.runLater :
Platform.runLater(() -> {
status.setText("");
statusIndicator.setVisible(false);
});
the other one simply modifies it in ordinary thread :
status.setText("");
statusIndicator.setVisible(false);
Both are working perfectly fine, only difference i know so far is that passing some runnable to Platform.runLater will keep the order of execution.
is there any other significat difference or motive to use Platform.runLater?
JavaFX has just a single UI thread
From Docs
The JavaFX scene graph, which represents the graphical user interface
of a JavaFX application, is not thread-safe and can only be accessed
and modified from the UI thread also known as the JavaFX Application
thread
In case you have long-running tasks, you will want to run them on background threads and after completion of such threads, you would want to update the result back to the UI. Under such scenario's, you use the updation surrounded with Platform.runlater(). Surrounding your code with Platform.runLater enables your code to communicate with the JavaFX Application thread.
Coming to your question :
is there any other significat difference or motive to use Platform.runLater?
I hope most of it is already answered, just to add
1 . You don't have to use Platform.runlater(), if you are already on the JavaFX Application thread
2 . As the Platform.runLater() doc says
Run the specified Runnable on the JavaFX Application Thread at some unspecified time in the future
We are not sure when the update will take place, it depends on the number of updates waiting to be processed. If a number of updates are waiting to be processed on the UI thread, it can take some time (such scenario normally doesn't happen)

JavaFX 2: background and Platform.runLater vs Task/Service

I'm pretty confused about the concept of Task/Service in JavaFX.
I have used a model based on a background thread for my background work, which call Platform.runLater for any update to the UI.
Let's say I'm not interested in a progress bar or such. I'm doing some real work on my model that must be updated in the view of the GUI (e.g a list of participants which updates over time based on some connection in the background, list of participant based on some user input, classified by age and origin). This is what I usually achieve with background threads that I start, and within which I use Platform.runLater.
Now in JavaFX 2 they have all this concurrency using Tasks and Services, suggesting that it is better to use them. But I don't see any examples that achieve what I'm talking about.
Updating the progress bar by binding some properties is nice (but those are information on the task not your model).
So, how can I actually update the content of my views based on my model? Should I call Platform.runLater from within the Task? If not, what is the mechanism? How do I catch when the tasks have succeed and get the result (the update of the actual model) to update the view?
The tutorials by Oracle unfortunately were not very good in this regard. Pointing me to some good tutorials would also help.
The Task and Service classes are designed to encourage good practice and proper use of concurrency for some (but not all) common scenarios in GUI programming.
A typical scenario is that the application needs to execute some logic in response to a user action which may take a long time (maybe a long calculation, or, more commonly, a database lookup). The process will return a result which is then used to update the UI. As you know, the long-running process needs to be executed on a background thread to keep the UI responsive, and the update to the UI must be executed on the FX Application Thread.
The Task class provides an abstraction for this kind of functionality, and represents a "one-off" task that is executed and produces a result. The call() method will be executed on the background thread, and is designed to return the result of the process, and there are event listeners for when the task completes that are notified on the FX Application thread. The developer is strongly encouraged to initialize the Task implementation with immutable state and have the call() method return an immutable object, which guarantees proper synchronization between the background thread and the FX Application Thread.
There are additional common requirements on these kinds of tasks, such as updating a message or the progress as the task progresses. The application may also need to monitor the life-cycle state of the class (waiting to run, running, completed, failed with an exception, etc). Programming this correctly is quite subtly difficult, as it necessarily involves accessing mutable state in two different threads, and there are many application developers who are unaware of the subtleties. The Task class provides simple hooks for this kind of functionality and takes care of all the synchronization.
To use this functionality, just create a Task whose call() method returns the result of your computation, register a handler for when the state transitions from RUNNING to SUCCEEDED, and run the task in a background thread:
final Task<MyDataType> task = new Task<MyDataType>() {
#Override
public MyDataType call() throws Exception {
// do work here...
return result ;
}
};
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
MyDataType result = task.getValue(); // result of computation
// update UI with result
}
});
Thread t = new Thread(task);
t.setDaemon(true); // thread will not prevent application shutdown
t.start();
The way this works behind the scenes is that the Task maintains a state property, which is implemented using a regular JavaFX ObjectProperty. The Task itself is wrapped in a private implementation of Callable, and the Callable implementation is the object passed to the superclass constructor. Consequently, the Callable's call() method is actually the method executed in the background thread. The Callable's call() method is implemented as follows:
Schedule a call on the FX Application thread (i.e. using Platform.runLater()) that updates the state, first to SCHEDULED, then to RUNNING
Invoke the call() method of the Task (i.e. the user-developed call() method)
Schedule a call on the FX Application Thread that updates the value property to the result of the call() method
Schedule a call on the FX Application Thread that updates the state property to SUCCEEDED
This last step will of course invoke listeners registered with the state property, and since the state change was invoked on the FX Application Thread, so to will those listeners' handle() methods.
For a full understanding of how this works, see the source code.
Commonly, the application may want to execute these tasks multiple discrete times, and monitor the current state representing all of the processes (i.e. "running" now means one instance is running, etc). The Service class simply provides a wrapper for this via a createTask() method. When the Service is started, it gets a Task instance by calling createTask(), executes it via its Executor, and transitions its own state accordingly.
There are of course many concurrency use cases that don't fit (at least cleanly) into the Task or Service implementations. If you have a single background Thread that is running for the entire duration of your application (so it represents a continuous process, rather than a one-off task), then the Task class is not a good fit. Examples of this might include a game loop, or (perhaps) polling. In these cases you may well be better off using your own Thread with Platform.runLater() to update the UI, but of course you have to handle proper synchronization of any variables that may be accessed by both threads. In my experience, it is worth spending some time thinking about whether these requirements can be re-organized into something that does fit into the Task or Service model, as if this can be done the resulting code structure is often much cleaner and easier to manage. There are certainly cases where this is not the case, however, in which case using a Thread and Platform.runLater() is appropriate.
One last comment on polling (or any other requirement for a periodically-scheduled background task). The Service class looks like a good candidate for this, but it turns out to be quite hard to manage the periodicity effectively. JavaFX 8 introduced a ScheduledService class which takes care of this functionality quite nicely, and also adds handling for cases such as repeated failure of the background task.

Excecuting two Async Tasks parallely at the same time ( Do i really need this?)

I read probably every tutorial and every forum discussion on that subject but still can't make it happen! and it is very frustrating.
it seems that the way to do it is to use executeOnExecutor() method with - AsyncTask.THREAD_POOL_EXECUTOR, and so i did in my code. but still,the second task only beeing executed only after the first one has finished and not in the same time.
My min sdk version is 2.3 and the maximum is 4.2, so i did the check:
if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.HONEYCOMB) {
engine.setEnginesTurn(true);
engineThread = new EngineThread(board,engine,activity,boardView);
rt = new RotateTask(boardView);
engineThread.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
rt.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else{
engine.setEnginesTurn(true);
engineThread = new EngineThread(board,engine,activity,boardView);
rt = new RotateTask(boardView);
engineThread.execute();
rt.execute();
}
Ignore the boolean variable here..it is not relevant,and also the other code since you wondered why i didn't post it. it is a mess but all working just fine,execpt for the execution of the two tasks. what am i doing wrong?
The reason i want the two tasks running parallely is: the first tasks is a computation task and the other one is a custom Hourglass image rotating animation while the computer is thinking (Its a game app).
EDIT: Ah.. and just wanted to include that i don't do the animation on the main UI thread is because i use sleep() for the animation ,so can't freeze the main thread.
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
So for parallel execution you can't use asynctask. The above is quoted from the doc. So for parallel execution i suggest you look at executor.
http://developer.android.com/reference/java/util/concurrent/Executor.html
It sounds like you are modifying the UI from the background thread in your AsyncTask. This is not thread safe and is probably causing the problem.
Keep your computation task on a separate thread and move your animation back onto the UI thread and (unless I am missing something) that should do the trick. Remember that anything that is drawn to the screen must be published on the main UI thread.
Just too much text. Please remove, there is a lot that is not needed.
Your design is complex, simplify it.
Why dont you just start 2 Async Tasks. Why have 2 jobs in 1 async task ? In one async task you can do your background thingy, and the other async task in the Pre and Post you can start your animation and stop your animation.

Using a timer to start a SwingWorker?

The task I need to perform involves requesting some data from an external server, performing some (fairly lengthy) processing on the data, and then updating the GUI with the results of the processing. Because the server might be unresponsive, the task is well suited to a SwingWorker: the doInBackground() method gets the results, and then the done method updates the GUI.
I need this to happen once every few seconds. I know I can just use a while loop and Thread.sleep, and create a new SwingWorker after each sleep. But everything I've read frowns upon using loops and sleep. I'd like to use a timer but:
Using a swing timer seems counterproductive; since they run on the EDT, I would essentially have no reason to use SwingWorker's doInBackground method. If the server were not responsive, the GUI would be unresponsive.
Using a java.util.Timer seems a bit wasteful: it seems to create a background thread for the TimerTask(), and since I am just creating a SwingWorker to do the actual work, I'm essentially creating a background thread that creates another background thread.
Can anybody tell me what's the best solution? I'd like to stick with SwingWorker since it seems ideally suited to the task, but I would like to avoid using a while loop if I can help it.
Thanks
You could use a ScheduledExecutorService:
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
// get a scheduled executor service with one thread
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// schedule the worker at an intervall of 5 seconds
scheduler.scheduleAtFixedRate(myWorker, 0, 5, TimeUnit.SECONDS);
I don't see why you couldn't use a Swing Timer to start a Swing Worker. What have you tried?
I think you're on the right track with SwingWorker. Now you need to look at its publish and process methods. As your processing progresses, you publish() an object from the background thread then the process() method is called on the Swing(EDT) thread so you can update the gui.
This way there aren't a bunch of timers and other threads to coordinate.
The javadocs have a straightforward example with prime numbers:
http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
How large is the set of data you are retrieving? If it is fairly small I would completely detach the task of fetching/processing and displaying.
Use some sort of in memory cache to hold the most recently processed set of data.
Use a javax.swing.Timer to update the GUI with the cached data.
Use a java.util.Timer to fetch the data from the database, process it and update the cache.
Be careful of synchronisation issues between the two times on your cache. You don't want your swing timer grabbing data at the same time as the other timer is updating it.

Categories

Resources