一、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.
----