Joker
Joker

Reputation: 11146

Confusion in ThreadPoolExecutor.afterExecute() example code

I am reading about ThreadPoolExecutor.afterExecute() and in the process found example code in JDK which looks like

  class ExtendedExecutor extends ThreadPoolExecutor {
   // ...
   protected void afterExecute(Runnable r, Throwable t) {
     super.afterExecute(r, t);
     if (t == null && r instanceof Future) {
       try {
         Object result = ((Future) r).get();
       } catch (CancellationException ce) {
           t = ce;
       } catch (ExecutionException ee) {
           t = ee.getCause();
       } catch (InterruptedException ie) {
           Thread.currentThread().interrupt(); // ignore/reset
       }
     }
     if (t != null)
       System.out.println(t);
   }
 }}

The code in the javadocs mentions

 r instanceof Future<?> 

and

result = ((Future<?>) r).get() 

From Understanding there should be FutureTask instead of Future.

r is a Runnable and Future doesn't implement Runnable but FutureTask does and is mentioned in the javadocs

If any one can please help me clear the clouds as i am confused here.

Upvotes: 0

Views: 675

Answers (4)

Preshit Maheshwari
Preshit Maheshwari

Reputation: 11

ThreadPoolExecutor.afterExecute(Runnable r, Throwable t) here r can be runnable in case u call executor.execute() or r can be a futureTask in case call is executor.submit(). FutureTask implements RunnableFuture which in turn extends Runnable and Future

So, intanceof holds true for Runnable and Future in case submit is called.

Upvotes: 1

Imus
Imus

Reputation: 822

I believe the reasoning behind just saying Future instead of FutureTask is that it's the most general thing we accept here.

Although in practice it most likely will be a FutureTask, it doesn't have to be.

Let's say purely for the sake of an example that r is an instance of the following class:

public class MyExample implements Runnable, Future {
    ....
}

The afterExecute(r,t) will work just fine, but r is not an instance of FutureTask

Upvotes: 0

muzzlator
muzzlator

Reputation: 742

It is possible to implement two interfaces at once. If the Runnable object also implements Future, then we can perform special handling of that object by casting it (after checking the cast will be fine). In the case of FutureTask<V> objects, these implement both Runnable and Future<V> and so the logic there will apply to them.

Edit: Not sure why the downvote but I suppose that means I better clarify

FutureTask<String> f = new FutureTask(
                          () -> { System.out.println("Hey"); },
                          "Hi");
f instanceof Runnable; // true
f instanceof Future; // true
executor.submit(f);
// Executor will call afterExecute(f, null) after running f.
// Prints:
// Hey
// Hi

The "Hi" is from the inside of the if statement which you're unsure if it ever gets executed (assuming that we're adding a print statement to the value of result, ie) f.get())

Upvotes: 1

FutureTask implements RunnableFuture,and RunnableFuture extends Runnable, Future,so it is the reseaon why you post FutureTask but can be cast to Future

Upvotes: 0

Related Questions