一、Future介紹
Future
以前我們如果有個方法action執行,比如去數據庫中查詢數據、上傳一個文件等,這個方法執行10分鐘,調用者就需要等10分鐘。
基於此,調用者可以先執行action,返回一個票據future,然後可以繼續做其他的事情,這樣就不阻塞了,完全異步化。然後可以根據future拿到action的結果。
自己怎麼實現一個Future呢?
代碼例子:
1 package com.cy.java8; 2 3 import java.util.concurrent.atomic.AtomicBoolean; 4 import java.util.concurrent.atomic.AtomicReference; 5 6 public class FutureInAction { 7 public static void main(String[] args) throws InterruptedException { 8 Future<String> future = invoke(() -> { 9 try { 10 Thread.sleep(10000); 11 return "I am finished"; 12 } catch (InterruptedException e) { 13 return "error"; 14 } 15 }); 16 17 System.out.println(future.get()); 18 System.out.println(future.get()); 19 System.out.println(future.get()); 20 //do other thing... 21 22 while (!future.isDone()) { 23 Thread.sleep(10); 24 } 25 System.out.println(future.get()); 26 } 27 28 /** 29 * 以前阻塞式的方式 30 * 31 * @param callable 32 * @param <T> 33 * @return 34 */ 35 private static <T> T block(Callable<T> callable) { 36 return callable.action(); 37 } 38 39 /** 40 * Future異步方式 41 * 42 * @param callable 43 * @param <T> 44 * @return 45 */ 46 private static <T> Future<T> invoke(Callable<T> callable) { 47 AtomicReference<T> result = new AtomicReference<>(); 48 AtomicBoolean finished = new AtomicBoolean(false); 49 Thread t = new Thread(() -> { 50 T value = callable.action(); 51 result.set(value); 52 finished.set(true); 53 }); 54 t.start(); 55 56 Future<T> future = new Future<T>() { 57 @Override 58 public T get() { 59 return result.get(); 60 } 61 62 @Override 63 public boolean isDone() { 64 return finished.get(); 65 } 66 }; 67 return future; 68 } 69 70 private interface Future<T> { 71 T get(); 72 73 boolean isDone(); 74 } 75 76 private interface Callable<T> { 77 T action(); 78 } 79 }
console打印:
null null null I am finished
二、jdk自帶的Future介紹
1 package com.cy.java8; 2 3 import java.util.concurrent.*; 4 5 public class FutureInAction2 { 6 public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { 7 /** 8 * 創建了一個線程池,但這個線程池裏面只有1根線程,單線程 9 * 這個線程是可以複用的,它執行完之後不會消失,會始終保持等待另外一個任務去執行 10 * 所以main函數執行結束之後,它不會退出的,所以還要shutdown 11 */ 12 ExecutorService executorService = Executors.newSingleThreadExecutor(); 13 Future<String> future = executorService.submit(() -> { 14 try { 15 Thread.sleep(10000); 16 return "I am finished."; 17 } catch (InterruptedException e) { 18 return "I am error."; 19 } 20 }); 21 22 //do other thing... 23 24 /** 25 * jdk的future和我們自己寫的不一樣,它get的時候會阻塞住,如果沒有結果它就阻塞住了,一直等結果 26 */ 27 //String value = future.get(); 28 //System.out.println(value); 29 30 //最多等10秒,如果沒有拿到結果就拉倒,拋TimeoutException 31 //String value2 = future.get(10000, TimeUnit.MILLISECONDS); 32 //System.out.println(value2); 33 34 while(!future.isDone()){ 35 Thread.sleep(10); 36 } 37 System.out.println(future.get()); 38 39 executorService.shutdown(); 40 } 41 }
三、CompletableFuture引入
能不能future的任務執行完成之後,你來回調我呢?異步回調,你完成了之後來回調我。
就像ajax的異步回調,post請求完成之後回調函數,來執行其他的東西。
CompletableFuture最大的作用就是幹這個的。
在講CompletableFuture之前,先說下它的原理,自己模擬實現一個CompletableFuture.
模擬代碼例子:
1 package com.cy.java8; 2 3 import java.util.concurrent.atomic.AtomicBoolean; 4 import java.util.concurrent.atomic.AtomicReference; 5 6 public class FutureInAction3 { 7 public static void main(String[] args) { 8 invoke(() -> { 9 try { 10 Thread.sleep(3000); 11 return "I am finished."; 12 } catch (InterruptedException e) { 13 return "I am error."; 14 } 15 }).setCompletable(new Completable<String>() { 16 @Override 17 public void complete(String s) { 18 System.out.println("complete. value = " + s); 19 } 20 21 @Override 22 public void exception(Throwable e) { 23 System.out.println("error..."); 24 e.printStackTrace(); 25 } 26 }); 27 28 //do other thing... 29 System.out.println("do other thing..."); 30 } 31 32 private static <T> Future<T> invoke(Callable<T> callable) { 33 AtomicReference<T> result = new AtomicReference<>(); 34 AtomicBoolean finished = new AtomicBoolean(false); 35 36 Future<T> future = new Future<T>() { 37 private Completable<T> completable; 38 39 @Override 40 public T get() { 41 return result.get(); 42 } 43 44 @Override 45 public boolean isDone() { 46 return finished.get(); 47 } 48 49 @Override 50 public void setCompletable(Completable<T> completable) { 51 this.completable = completable; 52 } 53 54 @Override 55 public Completable<T> getCompletable() { 56 return completable; 57 } 58 }; 59 60 Thread t = new Thread(() -> { 61 try { 62 T value = callable.action(); 63 result.set(value); 64 finished.set(true); 65 if (future.getCompletable() != null) { 66 future.getCompletable().complete(value); 67 } 68 } catch (Throwable cause) { 69 if (future.getCompletable() != null) { 70 future.getCompletable().exception(cause); 71 } 72 } 73 }); 74 t.start(); 75 76 return future; 77 } 78 79 private interface Future<T> { 80 T get(); 81 82 boolean isDone(); 83 84 void setCompletable(Completable<T> completable); 85 86 Completable<T> getCompletable(); 87 } 88 89 private interface Completable<T> { 90 void complete(T t); 91 92 void exception(Throwable cause); 93 } 94 95 private interface Callable<T> { 96 T action(); 97 } 98 }
console打印:
do other thing... complete. value = I am finished.
----