更多内容,前往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. win10下载jdk并配置环境变量

    win10下载jdk并配置环境变量 1. jdk下载 下载官网:Java SE开发套件15.0.2 2. jdk安装 一直点下一步就可以 3. 环境变量 配置 右键我的电脑--属性--高级系统设置-- ...

  2. python学习笔记-简介

    python简介 python是一种简单易学,功能强大的编程语言,他有高效的高层数据结构,简单而有效的实现面向对象编程.python是一种解释性语言,在多数平台的多个领域都是理想的脚本语言,特别适用于 ...

  3. JS中Promise

    Promise的作用: Promise是异步微任务,解决了异步多层嵌套回调的问题,让代码的可读性更高,更容易维护. Promise如何使用: Promise是ES6提供的一个构造函数,可以使用Prom ...

  4. pnn模型 待整理

    https://blog.csdn.net/qq_18293213/article/details/90262378?spm=1001.2101.3001.6650.5&utm_medium= ...

  5. Cubemx 生成工程代码失败的原因

    折腾了好久(躺)翻了很多解答试了试终于捣鼓正常了,就在这里汇总一下看到过的问题 1.文件名.工程名或者工程文件路径/库路径上有中文名 2.Cubemx的版本过高 3.java环境的版本不适配 4.可能 ...

  6. 第15章 授权:保护您的应用程序(ASP.NET Core in Action, 2nd Edition)

    本章包括 使用授权控制谁可以使用你的应用 对策略使用基于声明的授权 创建自定义策略以处理复杂的需求 根据所访问的资源授权请求 隐藏用户未经授权访问的Razor模板中的元素 在第14章中,我向您展示了如 ...

  7. 认识flutter

    flutter是谷歌的移动的ui框架,可以快速的在ios和安卓上构建高质量的原生用户界面.最主要的是完全免费开源.开发快,最重要的是使用flutter开发的开发工作者也越来越多了,生态圈也越来越好了. ...

  8. .Net 开发 web.config参数获取

    System.Configuration.ConfigurationSettings.AppSettings["title"] 对应着 web.config下面的 <conf ...

  9. python 循环 类型转换

  10. Java的由来

    Java 发展史 1.1.起源 20 世纪 90 年代,单片式计算机系统诞生,单片式计算机系统不仅廉价,而且功能强大,使用它 可以大幅度提升消费性电子产品的智能化程度. SUN 公司为了抢占市场先机, ...