這是本文件的舊版!
CompletableFuture - It may be useful to build chain of actions before execution.
Problem
下方這隻程式在Java8中應是相當常見:
CompletableFuture.supplyAsync(()->{ dumpCurrentThreadName("supplyAsync"); return new Response(); }).whenComplete((response, ex)->{ dumpCurrentThreadName("whenComplete"); // process response });它的問題是如果supplyAsync中的工作,在執行whenComplete前就結束了;當執行whenComplete時,有可能會使用client thread去執行工作而影響到工作接收的速度。以下是我的執行結果:
ForkJoinPool.commonPool-worker-3: supplyAsync main: whenComplete假如你的callback chain很長,遇到這個情況的機率就會越高。
How to resolve?
面對這個問題,在Java9中,允許你將實際的執行工作放到callback chain之後:
CompletableFuture<Response> asyncJob = new CompletableFuture<>(); asyncJob.whenComplete((response, ex)->{ dumpCurrentThreadName("whenComplete"); }); asyncJob.completeAsync(()->{ dumpCurrentThreadName("supplyAsync"); return new Response(); });輸出結果如下:
ForkJoinPool.commonPool-worker-3: supplyAsync ForkJoinPool.commonPool-worker-3: whenComplete這樣可以避免client thread跑去執行原本預期要async的工作,而增加了client thread的回應速度。
至於Java8目前我使用下面方式來達到lazy launch:
CompletableFuture<Response> asyncJob = new CompletableFuture<>(); job.thenApply((ret)->{ dumpCurrentThreadName("supplyAsync"); return new Response();rrentThreadName("runAsync"); }).whenComplete((response, ex)->{ dumpCurrentThreadName("whenComplete"); }); CompletableFuture.runAsync(()->{ asyncJob.complete(null); })
Reference