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服务获取,有的数据需要从缓存中读取,有的数据需要复杂的计算) 

posted @ 2019-05-22 13:27 废物大师兄 阅读(...) 评论(...) 编辑 收藏