从ThreadPoolTask​​Executor获取可调用性或将Runnable强制转换为Callable

时间:2015-06-11 19:08:02

标签: java multithreading spring threadpoolexecutor

我正在使用ThreadPoolTaskExecutor来执行我的任务,这是Callable接口的实现。我只想检查任务是否仍在池中(监控)。怎么做?我知道我可以从ThreadPoolExecutor获取队列但是如何将Runnable转换为Callable?

基本上我有这个可赎回的

public interface IFormatter extends Callable<Integer>{
    Long getOrderId();
}

我正在执行它

ThreadPoolExecutor.submit(new Formatter(order));

最后我想在一些异步方法中遍历ExecutorService的队列,并检查带有orderId的线程是否仍在那里。

2 个答案:

答案 0 :(得分:3)

正如this answer中所述,您可以通过手动创建FutureTask并通过Callable进行排名来控制execute包裹submit。否则,Callable会将您的ExecutorService包装到特定于Callable的对象中,并将其放入队列中,从而无法通过标准API查询FutureTask的属性。< / p>

使用自定义class MyFutureTask extends FutureTask<Integer> { final IFormatter theCallable; public MyFutureTask(IFormatter callable) { super(callable); theCallable=callable; } Long getOrderId() { return theCallable.getOrderId(); } }

threadPoolExecutor.execute(new MyFutureTask(new Formatter(order)));

通过public static boolean isEnqueued(ThreadPoolExecutor e, Long id) { for(Object o: e.getQueue().toArray()) { if(o instanceof MyFutureTask && Objects.equals(((MyFutureTask)o).getOrderId(), id)) return true; } return false; }

对其进行排队

您可以在队列中查询订单ID:

ExecutorService

这适用于任何ThreadPoolExecutor(假设它有一个队列)。如果您仅使用FutureTask,则可以自定义其public class MyThreadPoolExecutor extends ThreadPoolExecutor { public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); } public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); } public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); } @Override protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { if(callable instanceof IFormatter) return (FutureTask<T>)new MyFutureTask((IFormatter)callable); return super.newTaskFor(callable); } } 实例的创建(从Java 6开始),而不是依赖提交者执行此操作:

MyThreadPoolExecutor

然后,使用ThreadPoolExecutor而非IFormatter的实例,每次提交MyFutureTask实例时,都会使用FutureTask而不是标准ExecutorService自动换行。缺点是这仅适用于此特定[WordsUsed.index(word) for word in Phrase] ,并且泛型方法会为特殊处理生成未经检查的警告。

答案 1 :(得分:0)

由于您希望监视ExecutorService,请查看覆盖decorateTask()。然后,您可以装饰未来以监控其状态。