CompletableFuture引入

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

 

 

----

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章