一、CompletableFuture用法入門介紹
入門介紹的一個例子:
1 package com.cy.java8; 2 3 import java.util.Random; 4 import java.util.concurrent.CompletableFuture; 5 6 public class CompletableFutureInAction { 7 private final static Random RANDOM = new Random(System.currentTimeMillis()); 8 9 public static void main(String[] args){ 10 CompletableFuture<Double> completableFuture = new CompletableFuture<>(); 11 new Thread(() -> { 12 double value = get(); 13 completableFuture.complete(value); 14 }).start(); 15 16 System.out.println("do other things..."); 17 18 completableFuture.whenComplete((t, e) -> { 19 System.out.println("complete. value = "+ t); 20 if(e != null){ 21 e.printStackTrace(); 22 } 23 }); 24 } 25 26 private static double get(){ 27 try { 28 Thread.sleep(RANDOM.nextInt(3000)); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 return RANDOM.nextDouble(); 33 } 34 }
console打印:
do other things... complete. value = 0.8244376567363494
二、CompletableFuture.supplyAsync
CompletableFuture很少有直接new出來的方式去用的,一般都是通過提供的靜態方法來使用。
1.使用CompletableFuture.supplyAsync來構造CompletableFuture:
1 package com.cy.java8; 2 3 import java.util.concurrent.*; 4 5 import static com.cy.java8.CompletableFutureInAction.get; 6 7 public class CompletableFutureInAction2 { 8 9 public static void main(String[] args) { 10 /** 11 * 可以發現value=..沒有被打印,爲什麼呢? 12 * 因爲此方法構造出來的線程是demon的,守護進程,main執行結束之後就消失了,所以 13 * 根本沒來得及執行whenComplete中的語句 14 */ 15 CompletableFuture.supplyAsync(() -> get()) 16 .whenComplete((v, e) -> { 17 System.out.println("value = " + v); 18 if (e != null) { 19 e.printStackTrace(); 20 } 21 }); 22 23 System.out.println("do other things..."); 24 } 25 26 27 }
2.要將上面whenComplete中的語句執行,進行改造:
1 package com.cy.java8; 2 3 import java.util.concurrent.*; 4 import java.util.concurrent.atomic.AtomicBoolean; 5 import static com.cy.java8.CompletableFutureInAction.get; 6 7 public class CompletableFutureInAction2 { 8 9 public static void main(String[] args) throws InterruptedException { 10 AtomicBoolean finished = new AtomicBoolean(false); 11 12 CompletableFuture.supplyAsync(() -> get()) 13 .whenComplete((v, e) -> { 14 System.out.println("value = " + v); 15 if (e != null) { 16 e.printStackTrace(); 17 } 18 finished.set(true); 19 }); 20 21 System.out.println("do other things..."); 22 23 while(!finished.get()){ 24 Thread.sleep(1); 25 } 26 } 27 28 29 }
改寫之後, main線程發現如果finished沒有變爲true就會一直等1ms,直到whenComplete執行將finished變爲true。
3.上面的改寫很low,其實只要將守護線程變爲前臺進程,main結束後不會消失就行了。
1 package com.cy.java8; 2 3 import java.util.concurrent.*; 4 import static com.cy.java8.CompletableFutureInAction.get; 5 6 public class CompletableFutureInAction2 { 7 8 public static void main(String[] args){ 9 ExecutorService executorService = Executors.newFixedThreadPool(2, r -> { 10 Thread t = new Thread(r); 11 t.setDaemon(false); //非守護線程 12 return t; 13 }); 14 15 CompletableFuture.supplyAsync(() -> get(), executorService) 16 .whenComplete((v, e) -> { 17 System.out.println("value = " + v); 18 if (e != null) { 19 e.printStackTrace(); 20 } 21 }); 22 23 System.out.println("do other things..."); 24 25 //main執行結束之後,executorService線程不會結束,需要手動shutdown 26 executorService.shutdown(); 27 } 28 29 30 }
三、
----