[英]How to handle TimeoutException with ExecutorService and Futures?
I have the following example code and let's say that MyCallable("B")
takes longer than one second to execute, when the others execute quicker than one second. 我有以下示例代码,假设MyCallable("B")
执行时间超过一秒钟,而其他的执行速度则超过一秒钟。 Therefore inside my loop that calls Future.get()
, it will throw a TimeoutException
. 因此,在调用Future.get()
循环中,它将抛出TimeoutException
。
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(2);
List<Future<String>> futures = new ArrayList<Future<String>>();
futures.add(es.submit(new MyCallable("A")));
futures.add(es.submit(new MyCallable("B")));
futures.add(es.submit(new MyCallable("C")));
futures.add(es.submit(new MyCallable("D")));
futures.add(es.submit(new MyCallable("E")));
try {
for(Future<String> f : futures) {
try {
System.out.println("result " + f.get(1, TimeUnit.SECONDS));
}
catch (TimeoutException e) {
// how do I know which MyCallable() has timed out?
} catch (ExecutionException e) {
System.out.println(e.getMessage());
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
es.shutdown();
}
}
As expected each of the MyCallable() instances execute, but for the one that times out I would like to perform some error handling and this requires knowing which Callable
is associated with which Future
. 正如预期的那样,每个MyCallable()实例都会执行,但是对于超时的那个实例,我想执行一些错误处理,这需要知道哪个Callable
与哪个Future
关联。
Is there a mechanism for this association or is it up to my Callable
to handle all the error processing inside it's call()
method? 是否有这种关联的机制,还是由Callable
负责处理其call()
方法中的所有错误处理?
Seems like you could simply maintain a Map<Future<String>, Callable<String>>
instead of a List<Future<String>>
and retrieve the original Callable that way. 似乎您可以仅维护Map<Future<String>, Callable<String>>
而不是List<Future<String>>
然后以这种方式检索原始Callable。
If you want to get really clever, you could do it OO-style and extend ThreadPoolExecutor and create a Future decorator class. 如果您想变得非常聪明,则可以采用OO风格,并扩展ThreadPoolExecutor并创建Future装饰器类。 I think this is probably overkill, but you could do it like this: 我认为这可能是矫kill过正,但是您可以这样做:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class FutureWithCallable<T> implements Future<T> {
private final Callable<T> callable;
private final Future<T> wrapped;
public FutureWithCallable(Future<T> wrapped, Callable<T> callable) {
this.callable = callable;
this.wrapped = wrapped;
}
public Callable<T> getCallable() {
return callable;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return wrapped.cancel(mayInterruptIfRunning);
}
@Override
public T get() throws InterruptedException, ExecutionException {
return wrapped.get();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return wrapped.get(timeout, unit);
}
@Override
public boolean isCancelled() {
return wrapped.isCancelled();
}
@Override
public boolean isDone() {
return wrapped.isDone();
}
}
And then: 接着:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ExecutorServiceWithCallable extends ThreadPoolExecutor {
public ExecutorServiceWithCallable(int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue);
}
@Override
public <T> FutureWithCallable submit(Callable<T> callable) {
Future<T> future = super.submit(callable);
return new FutureWithCallable<T>(future, callable);
}
}
public class TimeoutException extends Exception Exception thrown when a blocking operation times out. 公共类TimeoutException扩展了Exception阻止操作超时时引发的异常。 Blocking operations for which a timeout is specified need a means to indicate that the timeout has occurred. 指定了超时的阻塞操作需要一种手段来指示发生了超时。 For many such operations it is possible to return a value that indicates timeout; 对于许多这样的操作,可以返回一个指示超时的值。 when that is not possible or desirable then TimeoutException should be declared and thrown. 如果不可能或不希望这样做,则应声明并抛出TimeoutException。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.