FutureTask 类
更多内容,前往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 类的更多相关文章
- Java并发编程:Future接口、FutureTask类
在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...
- FutureTask类
FutureTask类是Future 的一个实现,并实现了Runnable. 所以可通过Executor(线程池)来运行,也可传递给Thread对象运行. 假设在主线程中须要运行比較耗时的操作时.但 ...
- Future接口和FutureTask类【FutureTask实现了Runnable和Future接口】
Future API: public interface Future<V> { /** * Attempts to cancel execution of this task. This ...
- 并发系列(二)——FutureTask类源码简析
背景 本文基于JDK 11,主要介绍FutureTask类中的run().get()和cancel() 方法,没有过多解析相应interface中的注释,但阅读源码时建议先阅读注释,明白方法的主要的功 ...
- java 多线程:Callable接口;FutureTask类实现对象【Thread、Runnable、Callable三种方式实现多线程的区别】
Callable接口介绍: Java5开始,Java提供了Callable接口,像是Runnable接口的增强版,Callable接口提供了一个 call()方法可以作为线执行体. call()方法比 ...
- FutureTask类的get方法如何实现线程同步等待
接上篇JDK中线程中实现同步等待闭环的一种方式 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com),为什么使用了FutureTask中的get方法就可以实现线程的同步等待?这就将重点讲述下F ...
- Executor框架(七)Future 接口、FutureTask类
Future接口介绍 Future 表示异步计算的结果.它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果. Future 一般由 ExecutorService 的submi ...
- ThreadLocal类,实例测试,FutureTask类,实例测试。
1:测试ThreadLocal类, 为每个线程域保存局部变量.例如下面的例子. ThreadLocal为每个线程保存了一个Test对象, 那么当执行线程时,每个线程中的test具有唯一性.某一个线 ...
- Java多线程类FutureTask源码阅读以及浅析
FutureTask是一个具体的实现类,实现了RunnableFuture接口,RunnableFuture分别继承了Runnable和Future接口,因此FutureTask类既可以被线程执行,又 ...
- Java并发编程:Callable、Future和FutureTask
作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...
随机推荐
- python + uiautomator2 常用公共方法封装
前言 由于公司UI自动化框架底层用的是Uiautomator2,所以我就用Uiautomator2搭了一套UI自动化框架,思路其实和Appnium一样的. uiautomator2是一个自动化测试开源 ...
- CGTime CMTimeRange CMTimeMapping 小结
CMTime CMTimeRange CMTimeMapping 在使用 AVFoundation 框架处理多媒体资源时,通常会用到一些在 CoreMedia 框架中定义的结构体, 这里对其中描述时间 ...
- PHP Redis - zSet(有序集合)
有序集合与集合一样,string类型元素的集合,不允许重复的成员. 有序集合,每个元素都会关联一个 double 类型的分数.Redis 通过分数为集合的成员进行从小到大的排序 有序集合的成员是唯一的 ...
- keras构建1D-CNN模型
接触过深度学习的人一定听过keras,为了学习的方便,接下来将要仔细的讲解一下这keras库是如何构建1D-CNN深度学习框架的 from keras.datasets import imdb fro ...
- 26、EXCEL—插入的文字,如何修改其内的边间距
在形状格式-文本选项里面设置文本框的间距
- ES6 函数的扩展 rest参数
function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum; } add(2, ...
- openlayers-1 下载及安装使用
javascript - Import from in Openlayers - Geographic Information Systems Stack Exchange 在浏览器中运行开放层示例 ...
- 2022-03-02英语精读(Returning Youths)
今天早上没写代码,记录一下英语学习吧~ flee to sw/ from sb(sth)----coastal city-----get one's break----clinch a job/ de ...
- 关于SQLServer数据库DBCC CHECKIDENT命令
在SQLServer输入数据时,碰到有主键ID需要维护时,可使用IDENT_CURRENT和CHECKIDENT命令来维护. 一般我们的用法如下: 1) 查看且如有必要更正当前标识值: ...
- Altium Designer在原理图中复制报错InvalidParameter解决
Altium Designer 原理图复制出现 InvalidParameter Exception Occurred In Copy 解决方案为将下图红框中的√去掉 将红框中√去掉就点击右下 ...