【问题标题】:What is the runnable object passed in Java thread pool RejectedExecutionHandlerJava线程池RejectedExecutionHandler传入的runnable对象是什么
【发布时间】:2015-07-30 19:07:14
【问题描述】:

我有这样的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。 那么传递给rejectExecution 的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       

【问题讨论】:

标签: java threadpool


【解决方案1】:

问题是当您使用提交方法 TreadPoolExecutor(实际上是 AbstractExecutorService)提交任务时将其包装到 FutureTask。之后,您收到 FutureTask 而不是您的 Runnable。你可以调用执行不提交:

sExecutorService.execute(yourTask);

我认为没有办法从 FutureTask 获取您的任务。您只能为它调用运行。因此,如果您想调用 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();    

【讨论】:

  • 谢谢。我正在使用 submit() 因为我想要 Future 返回值。我批量提交许多任务,有时我需要返回并从“主”线程批量取消所有提交的任务。如果我使用 execute(),我不会得到 Future 返回值来取消()它们。
  • 用第二部分编辑我的答案 - 对于 FutureTask 并提交调用。
  • 好的,我不想运行它。我只想在其中设置一些字段,将其标记为被拒绝。这就是为什么我一直在寻找获取 MyTask 实例的原因。我想可能无法从您的回答中获取 MyTask 实例。 (我将探索其他方式)。谢谢
  • 编辑我的答案以显示从 FutureTask 获取任务的一种可能方法。希望它会有所帮助。
  • 谢谢。对于我的用例,我使用 submit() 将在任务被拒绝时抛出 RejectedExecutionException 的事实解决了它。我只是抓住它并处理任务。在创建线程池时使用ThreadPoolExecutor.AbortPolicy(),它将简单地重新抛出异常。
猜你喜欢
  • 2010-11-14
  • 2011-03-18
  • 2015-02-13
  • 2012-05-14
  • 1970-01-01
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多