原文链接
This post revisits Java 8’s CompletionStage API and specifically its implementation in the standard Java library CompletableFuture.
It represents a stage of a certain computation which can be done either synchronously or asynchronously.
1 2 3 4 5 6 7 8 9 static void runAsyncExample () { CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> { assertTrue(Thread.currentThread().isDaemon()); randomSleep(); }); assertFalse(cf.isDone()); sleepEnough(); assertTrue(cf.isDone()); }
关于sleepEnough?
By default (when no Executor is specified), asynchronous execution uses the common ForkJoinPool implementation, which uses daemon threads to execute the Runnable task. Note that this is specific to CompletableFuture. Other CompletionStage implementations can override the default behavior.
use executors
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static ExecutorService executor = Executors.newFixedThreadPool(3 , new ThreadFactory () { int count = 1 ; @Override public Thread newThread (Runnable runnable) { return new Thread (runnable, "custom-executor-" + count++); } }); static void thenApplyAsyncWithExecutorExample () { CompletableFuture<String> cf = CompletableFuture.completedFuture("message" ).thenApplyAsync(s -> { assertTrue(Thread.currentThread().getName().startsWith("custom-executor-" )); assertFalse(Thread.currentThread().isDaemon()); randomSleep(); return s.toUpperCase(); }, executor); assertNull(cf.getNow(null )); assertEquals("MESSAGE" , cf.join()); }
thenApply return value
thenAccept do not need to return a value
1 2 3 4 5 6 7 8 9 static void applyToEitherExample () { String original = "Message" ; CompletableFuture<String> cf1 = CompletableFuture.completedFuture(original) .thenApplyAsync(s -> delayedUpperCase(s)); CompletableFuture<String> cf2 = cf1.applyToEither( CompletableFuture.completedFuture(original).thenApplyAsync(s -> delayedLowerCase(s)), s -> s + " from applyToEither" ); assertTrue(cf2.join().endsWith(" from applyToEither" )); }
1 2 3 4 5 6 7 8 static void thenAcceptBothExample () { String original = "Message" ; StringBuilder result = new StringBuilder (); CompletableFuture.completedFuture(original).thenApply(String::toUpperCase).thenAcceptBoth( CompletableFuture.completedFuture(original).thenApply(String::toLowerCase), (s1, s2) -> result.append(s1 + s2)); assertEquals("MESSAGEmessage" , result.toString()); }
1 2 3 4 5 6 7 8 static void thenCombineAsyncExample () { String original = "Message" ; CompletableFuture<String> cf = CompletableFuture.completedFuture(original) .thenApplyAsync(s -> delayedUpperCase(s)) .thenCombine(CompletableFuture.completedFuture(original).thenApplyAsync(s -> delayedLowerCase(s)), (s1, s2) -> s1 + s2); assertEquals("MESSAGEmessage" , cf.join()); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CompletableFuture.allOf(futures.toArray(new CompletableFuture [futures.size()])).whenComplete((v, th) -> { futures.forEach(cf -> assertTrue(isUpperCase(cf.getNow(null )))); result.append("done" ); }); CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture [futures.size()])) .whenComplete((v, th) -> { futures.forEach(cf -> assertTrue(isUpperCase(cf.getNow(null )))); result.append("done" ); }); allOf.join();