我有一个期货清单,在每个未来完成后,我有一个应该执行的回调。
我正在使用Futures.successfulAsList来检查所有期货是否已经完成。但是,这并没有考虑回调的完成。
有没有办法确保回调完成?
我可以使用Futures.transform包装到另一个Future并检查完成情况,而不是Callback。但是,有了这个,我无法访问在未来包装中抛出的运行时异常。
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(20));
List<ListenableFuture<Object>> futures = new ArrayList<>();
for (int i = 1; i <= 20; i++) {
final int x = i * 100;
ListenableFuture<Object> future = service.submit(new Callable() {
@Override
public Object call() throws Exception {
Thread.sleep(10000 / x);
return x;
}
});
futures.add(future);
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
@Override
public void onSuccess(Object x) {
try {Thread.sleep((Integer) x * 10);} catch (Exception e) {}
System.out.println(x);
}
});
}
ListenableFuture<List<Object>> listFuture = Futures
.successfulAsList(futures);
System.out.println("Waiting...");
System.out.println(listFuture.get());
System.out.println("Done");
答案 0 :(得分:4)
如果您只想阻止所提交的N个任务的回调全部完成,则可以创建一个count
为countDown()
的{{3}}。然后只需拨打await()
它在每个回调完成时(无论是成功还是失败)和ListenableFutureTask<Void>
它在您想要阻止的位置。
或者,你可以做一些你在答案中所做的事情,但不是使用Runnable
和非操作SettableFuture<Void>
,而是使用set(null)
代替并{{1}} 1}}完成后就可以了。
答案 1 :(得分:1)
如果为每个回调创建另一个未来并确保它将在回调内完成,那该怎么办?
// create "callback" future here
futures.add(callbackFuture);
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
// do something with callbackFuture
}
@Override
public void onSuccess(Object x) {
try {Thread.sleep((Integer) x * 10);} catch (Exception e) {}
System.out.println(x);
// do something with callbackFuture
}
});
答案 2 :(得分:0)
谢谢,这有效!
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(20));
List<ListenableFuture<Void>> futures = new ArrayList<>();
for (int i = 1; i <= 20; i ++) {
final int x = i * 100;
ListenableFuture<Object> future = service.submit(new Callable(){
@Override
public Object call() throws Exception {
Thread.sleep(10000 / x);
return x;
}
});
//Blank runnable to evaluate write completion
Runnable callback = new Runnable(){
@Override
public void run() {
//do nothing
}
};
final ListenableFutureTask<Void> callbackFuture = ListenableFutureTask.create(callback, null);
futures.add(callbackFuture);
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onFailure(Throwable t) {
try {
t.printStackTrace();
}
finally {
callbackFuture.run();
}
}
@Override
public void onSuccess(Object x) {
try {
try {Thread.sleep((Integer)x*10);}catch(Exception e){}
System.out.println(x);
}
finally {
callbackFuture.run();
}
}
});
}
ListenableFuture<List<Void>> listFuture = Futures.successfulAsList(futures);
System.out.println("Waiting...");
System.out.println(listFuture.get());
System.out.println("Done");
答案 3 :(得分:0)
无睡眠的实现:
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(20));
List<ListenableFuture<Object>> futures = new ArrayList<>();
for (int i = 1; i <= 20; i++) {
final int x = i * 100;
ListenableFuture<Object> future = service.submit(new Callable() {
@Override
public Object call() throws Exception {
Thread.sleep(10000 / x);
return x;
}
});
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
@Override
public void onSuccess(Object x) {
try {Thread.sleep((Integer) x * 10);} catch (Exception e) {}
System.out.println(x);
}
});
/* all Callbacks added in one list (ExecutionList) and executed by order. If not defined 3d argument (Executor)
then callbacks executed sequentially at task thread.
*/
final SettableFuture<Object> lastCalledFuture = SettableFuture.create();
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onSuccess(Object result) {
lastCalledFuture.set(result);
}
@Override
public void onFailure(Throwable t) {
lastCalledFuture.setException(t);
}
});
futures.add(lastCalledFuture);
}
ListenableFuture<List<Object>> listFuture = Futures
.successfulAsList(futures);
System.out.println("Waiting...");
System.out.println(listFuture.get());
System.out.println("Done");