前言:Futrue的缺點有(1)get方法會阻塞 ,(2)不支持注冊回調方法 ,(3)不支持級聯操作
CompletableFuture彌補了這些缺點
直接上代碼:
public class CompletableFutureTest { public static void main(String[] args) throws Exception { // test1(); // test2(); // test3(); test4(); } //采用了callable+ future方式 ,get方法獲取任務的返回值會被阻塞住 public static void test1() throws Exception { ExecutorService executor = Executors.newCachedThreadPool(); Future<String> result = executor.submit(()->{ //模擬執行耗時任務 System.out.println("task doing..."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } //返回結果 return "result"; }); //這里只是將空閑的線程中斷,將線程池的狀態改為shutdown,不能繼續往線程池中添加任務 executor.shutdown(); System.out.println("task運行結果" + result.get()); } //采用了competableFuture,采用回調的方式獲取任務的返回值 public static void test2() throws Exception { //supplyAsync內部使用ForkJoinPool線程池執行任務 CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{ //模擬執行耗時任務 System.out.println("task doing..."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } //返回結果 return "100"; }).whenComplete((v,r)->{ System.out.println("計算結果是: "+v); }); //CompletableFuture里使用的線程池里的線程默認是daemon的。main線程結束后,整個程序也 //結束了,這里將main線程join后任務里的代碼才可以執行完 Thread.currentThread().join(); } //compeltableFuture可以支持級聯操作 public static void test3() throws Exception { IntStream.range(1,10).boxed().forEach( i -> CompletableFuture.supplyAsync(CompletableFutureTest::get) .thenAccept(CompletableFutureTest::display) .whenComplete((v,r)-> System.out.println(i +" have done") ) ); Thread.currentThread().join(); } public static void display(int data){ int value = ThreadLocalRandom.current().nextInt(10); try { System.out.println(Thread.currentThread().getName() +" display data "+ data+" will sleep "+value); TimeUnit.SECONDS.sleep(value); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +" dispaly have done with data = "+data); } public static int get(){ int value = ThreadLocalRandom.current().nextInt(10); try { System.out.println(Thread.currentThread().getName() +" get will sleep "+value); TimeUnit.SECONDS.sleep(value); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +" get have done "+value); return value; } //兩個線程分別執行任務,任務都執行完后再執行最后的runnable public static void test4() throws InterruptedException { CompletableFuture.supplyAsync(Object::new) .thenAcceptAsync(obj -> { try { System.out.println("obj ====== start"); TimeUnit.SECONDS.sleep(5); System.out.println("obj ====== " + obj); } catch (InterruptedException e) { e.printStackTrace(); } }).runAfterBoth(CompletableFuture.supplyAsync(() -> "hello") .thenAcceptAsync((v) -> { try { System.out.println("string ====== start"); TimeUnit.SECONDS.sleep(3); System.out.println("string ====== " + v); } catch (InterruptedException e) { e.printStackTrace(); } }), () -> System.out.println("finished")); Thread.currentThread().join(); } //一個線程計算奇數和,一個線程計算偶數和,main線程將他們相加 public static void test9() throws ExecutionException, InterruptedException { CompletableFuture<Integer> oddNumber = CompletableFuture.supplyAsync(()->{ try { System.out.println("開始計算奇數和 ..."); Thread.sleep(3_000); System.out.println("結束計算奇數和 ..."); } catch (InterruptedException e) { e.printStackTrace(); } return 1+3+5+7+9; }); CompletableFuture<Integer> evenNumber = CompletableFuture.supplyAsync(()->{ try { System.out.println("開始計算偶數和 ..."); Thread.sleep(5_000); System.out.println("結束計算偶數和 ..."); } catch (InterruptedException e) { e.printStackTrace(); } return 2+4+6+8; }); long startTime = System.currentTimeMillis(); CompletableFuture<Integer> resultFuturn = oddNumber.thenCombine(evenNumber,(odd,even)->{ return odd + even; }); System.out.println("==============="); System.out.println("運行結果是:"+resultFuturn.get()+" 總共耗時:"+ (System.currentTimeMillis()-startTime) +"毫秒"); } }