JDK Future
需要主动调用Future.get()
public static void testFutureUse() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> submit = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(3000);
System.out.println("begin do business");
return "foo";
}
});
System.out.println("submit finished");
System.out.println(submit.get());
System.out.println("result returned");
}
Guava Future Callback
public static void testCallbackUse() throws InterruptedException {
ListeningExecutorService listeningExecutor =
MoreExecutors.listeningDecorator(
Executors.newFixedThreadPool(2, new ThreadFactoryBuilder()
.setNameFormat("testCallbackUse-%d").build()));
ListenableFuture<String> listenableFuture =
listeningExecutor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("begin do business, owner=" + Thread.currentThread().getName());
//Thread.sleep(3000);
return "foo";
}
});
System.out.println("submit finished");
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("result successfully returned, owner=" + Thread.currentThread().getName());
}
@Override
public void onFailure(Throwable t) {
System.out.println("result failed");
}
}, MoreExecutors.directExecutor());
System.out.println("main await...");
Case1: Callable执行较快/基本无延迟
输出:
submit finished
begin do business, owner=testCallbackUse-0
result successfully returned, owner=main
main await...
Case2: Callable执行耗时较长(如网络调用)
这里用Sleep来代替,输出:
submit finished
begin do business, owner=testCallbackUse-0
main await...
result successfully returned, owner=testCallbackUse-0
可以看到,监听回调结果的执行线程是执行Callable的线程池worker
解释
It Depends.
Note: If the callback is slow or heavyweight, consider supplying an executor. If you do not supply an executor, addCallback will use a direct executor) [note: this is equivalent to
sameThreadExecutor()
which you passed in explicitly], which carries some caveats for heavier operations. For example, the callback may run on an unpredictable or undesirable thread:
- If the input Future is done at the time addCallback is called, addCallback will execute the callback inline. [that is, directly in the call to
addCallback
on the same thread whereaddCallback
was called]- If the input Future is not yet done, addCallback will schedule the callback to be run by the thread that completes the input Future, which may be an internal system thread such as an RPC network thread.