我有这样的thread pool with a RejectedExecutionHandler和一个Runnable任务。
sExecutorService = new ThreadPoolExecutor( ... new MyRejectionHandler() );
interface MyTask extends Runnable { ... }
class MyTaskImpl implements MyTask { ...}
我执行这样的任务
sExecutorService.submit(myTask);
在被拒绝的执行案例中,我希望得到被拒绝的Runnable(即MyTask),并在其中设置一些字段,将其标记为已拒绝。但我无法将其投射到MyTask。 那么runnable究竟是什么通过了被拒绝的执行?它似乎不是我提交的MyTask。如何在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
答案 0 :(得分:7)
问题是当您使用提交方法提交任务时,TreadPoolExecutor(实际上是AbstractExecutorService)将其包装到FutureTask。之后你会收到FutureTask而不是Runnable。你可以调用execute not submit:
sExecutorService.execute(yourTask);
我认为没有办法从FutureTask获取任务。你只能为它调用run。所以如果你想调用submit而你需要调用run - 只是不要转换为MyTask:
FutureTask myTask = (FutureTask) runnable;
myTask.run();
Object result = myTask.get();
其他方式如果你想访问你MyTask对象可以创建MyFutureTask扩展FutureTask,这将允许获取你的对象:
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;
}
}
此外,您需要扩展ThreadPoolExecutor并重新定义负责Runnable到FutureTask包装的newTaskFor方法:
public class MyThreadPoolExecutor extends ThreadPoolExecutor {
@Override
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new MyFutureTask(task, value);
}
}
之后,您可以使用MyThreadPoolExecutor作为ThreadPoolExecutor并拒绝任务处理:
MyFutureTask myFutureTask = (MyFutureTask) runnable;
MyTask myTask = (MyTask) myFutureTask.getMyTask();
// Now you can do what you want with you task:
myTask.doSomthing();