FutureTask

能異步毫不同步,能並行毫不串行java

1.  Future緩存

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

簡單用法:ide

 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執行。例如,上面的代碼能夠被改寫成以下:spa

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來執行。 blog

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服務獲取,有的數據須要從緩存中讀取,有的數據須要複雜的計算) get

相關文章
相關標籤/搜索