This discussion is archived
8 Replies Latest reply: Jan 23, 2013 11:20 PM by Marcello RSS

FutureTask - Question

Marcello Newbie
Currently Being Moderated
How is FutureTask used correctly ?

Suppose I have a FutureTask Object and I execute this task according to:
Thread t = new Thread( futureTask);
t.start();
The (JavaFX)-UI needs to stay responsive while the task is running. How am I supposed to wait for the tasks result ?

I think I have 2 options here:

1. In the task (last line in the call()-method I could call a callback method to notify the UI

or

2. I could wait for the result of the task according to:
try {               
     String s = (String) futureTask.get( 6, TimeUnit.SECONDS);               
     }catch (InterruptedException e1){                
     }catch (ExecutionException e1){ 
     }catch (TimeoutException e1){ 
     }                                                  
BUT: since .get() blocks I would need to exeucte these lines in a additional Thread, right ? reasonable design?
On the other hand I would like to take advantage of the TimeOut-Feature form this .get( 6, TimeUnit.SECONDS); method, which I do not have in option 1)

Please advise
  • 1. Re: FutureTask - Question
    shakir.gusaroff Expert
    Currently Being Moderated
    Hi. To develop multithreaded javafx applications you need to use javafx.concurrent package.
    For more information take a look at http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
  • 2. Re: FutureTask - Question
    Marcello Newbie
    Currently Being Moderated
    ..no useful examples in this article
  • 3. Re: FutureTask - Question
    James_D Guru
    Currently Being Moderated
    I think the article Shakir linked has everything you need. There's more information in the API docs for Worker http://docs.oracle.com/javafx/2/api/javafx/concurrent/Worker.html and Task http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html

    For example, you could do
    final FutureTask<MyDataType> futureTask = ... ;
    final Task<MyDataType> task = new Task<MyDataType>() {
      @Override
      public MyDataType call() throws Exception {
        Thread t = new Thread(futureTask);
        t.start();
        return futureTask.get(6, TimeUnits.SECONDS);
      }
    };
    task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
      @Override
      public void handle(WorkerStateEvent event) {
        MyDataType result = task.getValue();
        // process result ...
      }
    });
    task.setOnFailed(new EventHandler<WorkerStateEvent>() {
      @Override
      public void handle(WorkerStateEvent event) {
        Throwable t = task.getException();
        // Didn't complete; look at t to get more information
        // eg if (t instanceof TimeoutException) { timed out }
      }
    });
    new Thread(task).start(); // probably better to use Executors
  • 4. Re: FutureTask - Question
    Marcello Newbie
    Currently Being Moderated
    thanks for this example where you used 2 threads: One for executing the task (to keep the UI responsive) and another for waiting for the result (with timeout-feature).
    I was wondering whether this could be achieved in only 1 thread
  • 5. Re: FutureTask - Question
    shakir.gusaroff Expert
    Currently Being Moderated
    Instead of java.util.concurrent.FutureTask<V> use javafx.concurrent.Task<V>.

    javafx.concurrent.Task<V> defined as
     public abstract class Task<V>
    extends java.util.concurrent.FutureTask<V>
    implements Worker<V>, EventTarget
  • 6. Re: FutureTask - Question
    James_D Guru
    Currently Being Moderated
    Shakir, that's true, but I don't see how you would wait for a timeout with using only a single thread. The point is that you need one thread to do the work, and another (also non-FX Application thread) to block for a specified time and retrieve the result if it's available.

    I may be missing something though...
  • 7. Re: FutureTask - Question
    James_D Guru
    Currently Being Moderated
    The more I think about this, the more I'm convinced you can't do it with a single thread. Assuming the original task you're using doesn't manage its out timeout (in which case you wouldn't be using the version of get(...) which times out, but I'll come back to this later), you need one thread to do the actual work, and another thread to block until the work is either complete or times out. As you point out in your original post, neither of these can be the FX application thread, because the UI would become unresponsive.

    I struggle to see any common use case for this though. There are really two kinds of "long running task" that I've ever worked with. One is computational (image processing, or highly-complex scientific computations). For these, you can typically measure the amount of progress. In a UI application environment, one would typically display the progress to the user, and then allow them to cancel the operation if it were taking too long. (Do you really want to throw out those valuable 6 seconds of computation if the operation were 90% complete?) The FX Worker and Task API give lots of hooks for this kind of functionality.

    The other type "long running task" is data retrieval/storage, typically over a network (say from a networked database). For this use case, the usual pattern is to have a separate layer (which may be as simple as a single class) which handles communication with the underlying data provider. Typically this layer would be configured with a timeout value and its operations would throw exceptions if the timeout occurs. (For example, in JDBC you would manage this using Statement.setQueryTimeout(...); there are similar mechanisms in JPA/Hibernate) The task you implement would then effectively be managing its own timeout, in that exceptions would be thrown if the timeout occurred. In this case, you can simply let the exception propagate from the call(...) method of the Task, and then deal with it using a setOnFailed(...).

    In neither of these use cases would I use the timeout version of get(...). In cases where you can't measure the progress, and the underlying operation doesn't provide its own timeout functionality, then you can wrap the task as I showed earlier. Incidentally, in that case you would probably want to catch the TimeoutException if it occurred and cancel the underlying task, so that your thread resources are properly cleaned up. Then rethrow the exception to let the setOnFailed(...) handler do its stuff.
  • 8. Re: FutureTask - Question
    Marcello Newbie
    Currently Being Moderated
    Thanks James
    The other type "long running task" is data retrieval/storage, typically over a network (say from a networked database).
    For this use case, the usual pattern is to have a separate layer (which may be as simple as a single class) which handles communication with the underlying data provider. Typically this layer would be configured with a timeout value and its operations would throw exceptions if the timeout occurs
    I agree.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points