更多内容,前往IT-BLOG

一、什么是 Future和 FutureTask


FutureTask 的 Future就源自于它的异步工作机制,如果我们在主线程中直接写一个函数来执行任务,这是同步的任务,也就是说必须要等这个函数返回以后我们才能继续做接下的事情,但是如果这个函数返回的结果对接下来的任务并没有意义,那么我们等在这里是很浪费时间的,而 FutureTask就提供了异步返回结果的机制,当执行一个 FutureTask任务的时候,系统可以接着做别的任务,在将来某个时间,FutureTask任务完成后会返回 FutureTask对象来包装返回的结果,只要调用这个对象的 get()方法即可获取返回值。当然多线程中继承 ThreadPoolExecutor和实现 Runnable也可以实现异步工作机制,可是他们没有返回值。这时可以使用 FutureTask包装 Runnable或者 Callable对象,再使用 FutureTask来执行任务。

Future接口和其唯一的实现类 FutureTask类一般用于表示异步计算的结果。Future接口下提供方法来检查计算是否完成,等待其完成,并检索计算结果。 结果只能在计算完成后使用get() 进行检索,如有必要可进行阻塞,直到准备就绪。 取消由 cancel方法执行,isCancelled方法用于检测计算是否被取消,isDone方法用于检测计算是否完成。 提供其他方法来确定任务是否正常完成或被取消。

二、FutureTask 的使用


根据 FutureTask被执行的进度,FutureTask对象共有3种状态:
【1】未启动:创建了一个 FutureTask对象但没有执行 futureTask.run();
【2】已启动:futureTask.run()方法正在执行;
【3】已完成:futureTask.run()正常执行结束,或者 futureTask被取消(futureTask.cancel()),或者执行 futureTask.run()时抛出异常而异常结束;

FutureTask 的启动


FutureTask实现了 Future接口和 Runnable接口,因此 FutureTask对象的执行有两种方式:

【1】交给线程池的 execute() 或 submit() 执行;

 1 import java.util.concurrent.*;
2 import static java.util.concurrent.TimeUnit.MILLISECONDS;
3
4
5 class test{
6 public static void main(String[] args) throws InterruptedException {
7 ThreadPoolExecutor tpe = new ThreadPoolExecutor(5, 10,100, MILLISECONDS, new ArrayBlockingQueue<Runnable>(5));
8 //用FutureTask包装Runnable或者Callable对象
9 FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
10 @Override
11 public String call() {
12 try{
13 String a = "return String";
14 return a;
15 }
16 catch(Exception e){
17 e.printStackTrace();
18 return "exception";
19 }
20 }
21 });
22 //交给线程池的Execute或submit方法执行
23 tpe.submit(future);
24 try{
25 System.out.println(future.get());
26 }
27 catch(Exception e){
28 e.printStackTrace();
29 }
30 finally{
31 tpe.shutdown();
32 }
33 }
34 }

FutureTask是一个基于AQS同步队列实现的一个自定义同步组件,通过对同步状态 state的竞争实现 acquire或者 release操作。FutureTask 的内部类 Sync实现了 AQS接口,通过对 tryAcquire等抽象方法的重写和模板方法的调用来实现内部类 Sync的 tryAcquireShared等方法,然后聚合 Sync的方法来实现 FutureTask的get,cancel等方法;

FutureTask的 get方法最终会调用 AQS.acquireSharedInterruptibly方法,这个方法操作成功的条件是同步状态为 RAN或者 CANCELLED,也就是说如果这个 FutureTask有线程E正在执行,那么这个 FutureTask的状态是 RUN,因此 AQS.acquireSharedInterruptibly方法调用失败,此时调用 get方法的线程被阻塞,添加到等待队列中(如下图线程D,其中A,B,C是已经被阻塞添加到等待队列中的线程)。当前面执行 FutureTask的线程E执行完毕,那么以原子方式更新同步状态 state的值为RAN,并执行 AQS.release方法,然后唤醒等待队列中的第一个节点中的线程A,此时线程A出队列获得同步状态,并原子设置 state为 RUN,当线程A执行完毕,把 state原子更新为 RUN,然后唤醒线程B,以此类推,因此对于 FutureTask,同一时间只有一个线程执行这个任务。

四、FutureTask使用场景


当一个线程需要等待另一个线程把某个任务执行完以后它才能继续执行时;

有若干线程执行若干任务,每个任务最多只能被执行一次;

当多个线程试图执行同一个任务,但只能允许一个线程执行此任务,其它线程需要等这个任务被执行完毕以后才能继续执行时;

FutureTask 类的更多相关文章

  1. Java并发编程:Future接口、FutureTask类

    在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...

  2. FutureTask类

    FutureTask类是Future 的一个实现,并实现了Runnable. 所以可通过Executor(线程池)来运行,也可传递给Thread对象运行.  假设在主线程中须要运行比較耗时的操作时.但 ...

  3. Future接口和FutureTask类【FutureTask实现了Runnable和Future接口】

    Future API: public interface Future<V> { /** * Attempts to cancel execution of this task. This ...

  4. 并发系列(二)——FutureTask类源码简析

    背景 本文基于JDK 11,主要介绍FutureTask类中的run().get()和cancel() 方法,没有过多解析相应interface中的注释,但阅读源码时建议先阅读注释,明白方法的主要的功 ...

  5. java 多线程:Callable接口;FutureTask类实现对象【Thread、Runnable、Callable三种方式实现多线程的区别】

    Callable接口介绍: Java5开始,Java提供了Callable接口,像是Runnable接口的增强版,Callable接口提供了一个 call()方法可以作为线执行体. call()方法比 ...

  6. FutureTask类的get方法如何实现线程同步等待

    接上篇JDK中线程中实现同步等待闭环的一种方式 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com),为什么使用了FutureTask中的get方法就可以实现线程的同步等待?这就将重点讲述下F ...

  7. Executor框架(七)Future 接口、FutureTask类

    Future接口介绍   Future 表示异步计算的结果.它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果.   Future 一般由 ExecutorService 的submi ...

  8. ThreadLocal类,实例测试,FutureTask类,实例测试。

    1:测试ThreadLocal类,  为每个线程域保存局部变量.例如下面的例子. ThreadLocal为每个线程保存了一个Test对象,  那么当执行线程时,每个线程中的test具有唯一性.某一个线 ...

  9. Java多线程类FutureTask源码阅读以及浅析

    FutureTask是一个具体的实现类,实现了RunnableFuture接口,RunnableFuture分别继承了Runnable和Future接口,因此FutureTask类既可以被线程执行,又 ...

  10. Java并发编程:Callable、Future和FutureTask

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

随机推荐

  1. flutter RaisedButton 设置最小宽度和高度

    flutter中可以通过ButtonTheme为RaisedButton设置最小宽度,示例代码如下: ButtonTheme( minWidth: 200.0,//设置最小宽度 height: 100 ...

  2. python -m pip install --upgrade pip 解决升级不成功问题

    使用pip 提示更新: You are using pip version 18.1, however version 20.0.2 is available. You should consider ...

  3. UNIT TWO

    声明 基于8086的寄存器共14个16位的,分别是 ax  bx  cx  dx  (通用寄存器) si  di  bp  sp    (基址与变址寄存器) cs  ss  ds  es   (段寄存 ...

  4. CORS预检

    CORS是一种常见的跨域机制,一般由服务端提供一个Access-Control-Allow-Origin头来解决问题,但是这仅对一些"简单请求"有效.那么何谓"简单请求& ...

  5. #Python #微信 #消息防撤回 Python实现微信防撤回

    微信(WeChat)是腾讯公司于2011年1月21日推出的一款社交软件,8年时间微信做到日活10亿,日消息量450亿.在此期间微信也推出了不少的功能如:"摇一摇"."漂流 ...

  6. SaltStack学习笔记

    SaltStack三大功能: 1. 远程执行 2. 配置管理  (状态) 3.云管理 运维三板斧:监控.执行.配置 四种运行方式: 1.Local 2. Minion/Master   C/S架构 3 ...

  7. 连接打印机Lodop

    <div class="panel-body"> <div class="row show-grid"> <div class=& ...

  8. 编译安装php-fpm并添加nginx支持

    编译安装php-fpm 环境准备 yum -y install gcc automake autoconf libtool make install gcc gcc-c++ glibc bison b ...

  9. reactHooks_useEffect

    当在直接在组件内使用setState时,会产生"渲染次数过多"的错误 例如: const A = ( ) => {   const [num,setNum] = useSta ...

  10. java 与 JSON

    Java 与 JSON JSON 是不同程序之间传递信息的一种格式.本文描述了 JSON 在 Java 中的应用. 目前 Java 中比较主流的相关解析工具有谷歌提供的 Gson 和阿里提供的 Fas ...