Как объяснено в this answer, вы можете получить контроль над FutureTask
обертывание Callable
путем создания его вручную и enqueuing через 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();
}
}
enqueuing его через 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;
}
Это работает для любого 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
, а общий метод генерирует непроверенное предупреждение для специального лечения.
Вы не можете, так как эти «Runnable's» на самом деле являются экземплярами «FutureTask», которые обертывают оригинальную «Callable». Чтобы сделать исходный 'Callable' доступным, вы должны заменить созданный' ExecutorService' '' FutureTask 'вручную '. Сравните с [этим ответом] (http://stackoverflow.com/a/30789565/2711488). – Holger
Я обновил свой вопрос. Можно ли вызвать getOrderId с вашим решением? – bilak