Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the runnable object passed in Java thread pool RejectedExecutionHandler

I have thread pool with a RejectedExecutionHandler like this and a Runnable task.

sExecutorService = new ThreadPoolExecutor( ...    new MyRejectionHandler() );

interface MyTask extends Runnable { ... }

class MyTaskImpl implements MyTask { ...}     

i execute a task like this

   sExecutorService.submit(myTask);        

in rejectedExecution case i was hoping to get hold of rejected Runnable (ie MyTask) and set some field in it marking it as rejected. But i am not able to cast it to MyTask. So what exactly is the runnable passed t o rejectedExecution ? It appears not MyTask i submitted . And how can i get hold of the rejected task in RejectedExecutionHandler.

public class MyRejectionHandler implements RejectedExecutionHandler{  
   public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor)  {
    MyTask myTask = (MyTask) runnable; // exception
    myTask.doSomething();
   }
java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to MyTask       
like image 448
Ratheesh Pai Avatar asked Jun 07 '12 12:06

Ratheesh Pai


People also ask

What is pool of thread in Java?

What is ThreadPool in Java? A thread pool reuses previously created threads to execute current tasks and offers a solution to the problem of thread cycle overhead and resource thrashing.

What is keepAliveTime in ThreadPoolExecutor?

keepAliveTime - when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating. unit - the time unit for the keepAliveTime argument. workQueue - the queue to use for holding tasks before the are executed.

What happens if you submit a task when the queue of the thread pool is already filled?

Remember: If corePoolSize or more threads are running, the executor prefers queuing the task than creating a new thread. If the queue is full and creating a new thread would exceed maximumPoolSize the submitted task is rejected by the executor.


1 Answers

The problem is when you submit task with submit method TreadPoolExecutor (actually AbstractExecutorService) wrap it to FutureTask. After that you receive FutureTask not your Runnable. You can call execute not submit:

sExecutorService.execute(yourTask);

I don't think there is a way to get your task from FutureTask. You can only call run for it. So if you want to call submit and you need to call run - just do not convert to MyTask:

FutureTask myTask = (FutureTask) runnable;
myTask.run();
Object result = myTask.get();

Other way if you want to access you MyTask object can be creating of MyFutureTask extends FutureTask, that will allow get your object:

public MyFutureTask<V> extends FutureTask<V> {

    private Runnable myTask;

    public MyFutureTask(Runnable runnable, V result) {
        super(runnable, result);
        this.myTask = runnable;
    }

    public Runnable getMyTask() {
        return myTask;
    }        
}

Also you need to extends ThreadPoolExecutor and redefine newTaskFor method that is responsible for Runnable to FutureTask wraping:

public class MyThreadPoolExecutor extends ThreadPoolExecutor {

    @Override
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new MyFutureTask(task, value);            
    }
}

After that you can use MyThreadPoolExecutor as a ThreadPoolExecutor and in rejecting task processing:

MyFutureTask myFutureTask = (MyFutureTask) runnable;
MyTask myTask = (MyTask) myFutureTask.getMyTask();
// Now you can do what you want with you task:
myTask.doSomthing();    
like image 171
alexey28 Avatar answered Nov 15 '22 08:11

alexey28