JDK Future
需要主动调用Future.get()
public static void testFutureUse() throws ExecutionException, InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(2);Future<String> submit = executor.submit(new Callable<String>() {@Overridepublic 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>() {@Overridepublic 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>() {@Overridepublic void onSuccess(String result) {System.out.println("result successfully returned, owner=" + Thread.currentThread().getName());}@Overridepublic void onFailure(Throwable t) {System.out.println("result failed");}}, MoreExecutors.directExecutor());System.out.println("main await...");
Case1: Callable执行较快/基本无延迟
输出:
submit finishedbegin do business, owner=testCallbackUse-0result successfully returned, owner=mainmain await...
Case2: Callable执行耗时较长(如网络调用)
这里用Sleep来代替,输出:
submit finishedbegin do business, owner=testCallbackUse-0main 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
addCallbackon the same thread whereaddCallbackwas 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.
