FutureTask


能異步絕不同步,能並行絕不串行

1.  Future

一個Future代表一個異步計算的結果。Future提供檢查計算是否完成、等待計算完成並獲取計算結果的方法。只有當計算完成以后,才可以使用get方法檢索結果,否則將會阻塞直到計算完成。通過調研cancel方法可以取消執行。另外,還提供了檢查任務是正常完成還是被取消的方法。一旦計算完成,這個計算不能被取消。

簡單用法:

 1 public class App {
 2     ExecutorService executorService = Executors.newFixedThreadPool(3);
 3     ArchiveSearcher searcher = new ArchiveSearcher();
 4 
 5     void showSearch(final String target) throws InterruptedException {
 6         Future<String> future = executorService.submit(new Callable<String>() {
 7             public String call() {
 8                 return searcher.search(target);
 9             }
10         });
11         
12         displayOtherThings(); // do other things while searching
13         
14         try {
15             displayText(future.get()); // use future
16         } catch (ExecutionException ex) { 
17             cleanup(); 
18             return; 
19         }
20     }
21 }

FutureTask類是Future的實現,它同時也實現了Runnable,因此也可以被Executor執行。例如,上面的代碼可以被改寫成如下:

1 FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
2     public String call() {
3         return searcher.search(target);
4     }
5  });
6  executor.execute(future);

2.  FutureTask 

  • 一個可取消的異步計算
  • 該類提供了Future的基本實現,提供了啟動和取消計算、查詢計算是否完成以及檢索計算結果的方法
  • 只有在計算完成后才可檢索結果;如果計算尚未完成,get方法將阻塞
  • 計算完成以后,計算不能重啟或取消(除非調用runAndReset方法) 

一個FutureTask可以用來包裝一個Callable或Runnable對象。因為FutureTask實現了Runnable接口,一個FutureTask可以被提交給一個Executor來執行。 

3.  示例

 1 package com.cjs.example;
 2 
 3 import java.util.concurrent.*;
 4 
 5 /**
 6  * @author ChengJianSheng
 7  * @date 2019-05-22
 8  */
 9 public class App {
10 
11     public static void main(String[] args) throws Exception {
12 
13         long t1 = System.currentTimeMillis();
14 
15         ExecutorService executorService = Executors.newFixedThreadPool(3);
16 
17         FutureTask<String> heatUpWaterFuture = new FutureTask<String>(new Callable<String>() {
18             @Override
19             public String call() throws Exception {
20                 System.out.println("燒開水...");
21                 Thread.sleep(3000);
22                 return "ok";
23             }
24         });
25 
26 
27         FutureTask<String> cookMealsFuture = new FutureTask<String>(new Callable<String>() {
28             @Override
29             public String call() throws Exception {
30                 System.out.println("煮飯...");
31                 Thread.sleep(5000);
32                 return "ok";
33             }
34         });
35 
36         executorService.submit(heatUpWaterFuture);
37         executorService.submit(cookMealsFuture);
38 
39         System.out.println("炒菜...");
40 
41         Thread.sleep(2000);
42 
43         System.out.println("菜炒好了了");
44 
45         if (heatUpWaterFuture.get(5000, TimeUnit.SECONDS) == "ok"
46                 && cookMealsFuture.get(5000, TimeUnit.SECONDS) == "ok") {
47             System.out.println("開飯了...");
48         }
49 
50         long t2 = System.currentTimeMillis();
51         System.out.println("做飯用時:" + (t2-t1) + "ms");
52 
53     }
54 } 

輸出

1 燒開水...
2 煮飯...
3 炒菜...
4 菜炒好了了
5 開飯了...
6 做飯用時:5014ms 

在實際開發過程中,將那些耗時較長,且可以並行的操作都封裝成一個FutureTask(比如:有的數據通過調用dubbo服務獲取,有的數據需要從緩存中讀取,有的數據需要復雜的計算) 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM