正如中所解释的这个答案,你可以控制FutureTask
包裹着Callable
通过手动创建它并通过排队execute
。否则,submit
将包裹你的Callable
进入一个ExecutorService
- 特定对象并将其放入队列中,从而无法查询该对象的属性Callable
通过标准 API。
使用自定义FutureTask
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)));
,
您可以查询队列中的订单ID:
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;
}
这适用于任何ExecutorService
(假设它有一个队列)。如果您使用的是ThreadPoolExecutor
只是,您可以自定义其创建FutureTask
实例(从 Java 6 开始),而不是依赖提交者执行此操作:
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);
}
}
然后,使用一个实例MyThreadPoolExecutor
代替ThreadPoolExecutor
每提交一个IFormatter
实例将自动包装使用MyFutureTask
而不是标准FutureTask
。缺点是这只适用于这个特定的ExecutorService
通用方法会针对特殊处理生成未经检查的警告。