9

I'm quite new to executer services. Liked doing everything myself, but I think it's time to trust these services.

I want to hand by Executer a Runnable. The executer wraps that in a FutureTask and hands it back to me. Now I call poll the done() method. But I would like to be notified when then done() method would return true.

There is a get() method that blocks until the Runnable has finished, but then I would need a extra thread for every job, just to see when it's finished.

Can I hand my executer some extra Callable to get notified about the task finishing?

What's the way to go here? I could add some code to the end of the run method, but then done() might still be false...

Franz Kafka
  • 10,623
  • 20
  • 93
  • 149

4 Answers4

3

If you want to do one task after another its better to do it in the same thread.

Executor executor =
final Runnable runnable = 
executor.execute(new Runnable() {
    public void run() {
         runnable.run();
         // do something after the run() has finished.
    }
 });

This way it will do whatever you want done after the runnable in the same thread and you don't need to poll or use another thread.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I also have multithreading question [here](http://stackoverflow.com/questions/29130563/how-can-i-terminate-tasks-that-have-timed-out-in-multithreading/). I am not sure how should I use cancel on my future task so wanted to check with you on that. If possible, can you help me out over there. – john Mar 19 '15 at 07:09
3

I'd advise taking a look at the com.google.common.util.concurrent package in Guava, specifically the ListenableFuture type and the code related to it.

Once the next release (r10) is out, it'll be easy to create an ExecutorService that returns ListenableFutures using MoreExecutors.listeningDecorator(ExecutorService). You can also currently wrap your Runnables/Callables in a ListenableFutureTask yourself.

final ListenableFutureTask<?> task = new ListenableFutureTask<Object>(
    runnable, null);
executor.submit(task);
task.addListener(new Runnable() {
  public void run() {
    // do whatever
  }
}, listenerExecutor);
ColinD
  • 108,630
  • 30
  • 201
  • 202
  • Isn't this a complicated way of Peter Lawrey's approach. – irreputable Jun 14 '11 at 16:51
  • Maybe with that decorator it could be neat code. When is v.10 coming? Is there some beta to download? – Franz Kafka Jun 14 '11 at 17:00
  • @irreputable: In Peter's approach, the handling of what to do after the task completes is lumped in as part of the task that is submitted to the executor. If the task were cancelled, for example, you wouldn't find out. As written, an exception in the delegate's `run()` would also cause the part after not to run. Plus you're tying the stuff that happens after to the same thread as the task itself, which you may not want. – ColinD Jun 14 '11 at 17:06
  • does your framework protect against errors, e.g. OutOfMemoryError? So I can be sure the registered listener will allways be called? – Franz Kafka Jun 14 '11 at 17:13
  • @Franz: I seem to recall hearing something about July for r10, but there's no official date. You could build the latest source of course, and it's actually pretty easy to extend `AbstractExecutorService` (in 1.6) to do make a listening decorator. – ColinD Jun 14 '11 at 17:19
  • @Franz: I'm not sure that anything can guarantee what will happen if something like `OutOfMemoryError` occurs (that's why it's an `Error`). That said, when a `FutureTask` runs it does catch any `Throwable` and store it and call `done()`, so it will certainly try to notify listeners when that happens. – ColinD Jun 14 '11 at 17:31
  • BTW, given source code would not compile. There is no `ExecutorService.submit(FutureTask ft)`, it only accepts `Runnable` and `Callable` as args. – mindas Jul 21 '11 at 17:19
1

If you can make a specific assumption of using a java.util.concurrent.ThreadPoolExecutor, then you can use its hook methods; afterExecute() and beforeExecute().

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

They are not as elegant as the ListenableFuture, but it might be an adequate solution provided you need only one type of a "listener" for a given executor instance.

sjlee
  • 7,726
  • 2
  • 29
  • 37