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/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...
随机推荐
- DOSBox进行文件操作
1.使用DOSBox进行汇编语言的学习 2.输入edit进行asm文件编辑,保存后输入masm 文件名.asm,进行编译:输入link 文件名进行连接:输入debug 文件名.exe进行执行,并进行调 ...
- 非线性优化-SLAM14CP6
在前声明下面有一部分直接引用高翔老师SLAM14讲中的内容.因为我实在是看不懂.临时放在这里.以后有用到再做详细研究. 在SLAM14讲的CP2中第一次引入运动方程以及观测方程来描述物体带着传感器在空 ...
- Java 基础(二)
类的初始 类中包括:属性,方法. 快速使用 我们都是人,而人的共同特点有很多. 比如:名字,年龄,性别,吃饭,睡觉... // 定义类 public class Person { // 定义属性 St ...
- 微服务注册到Nacos上的Ip错误,是内网ip不是公网ip
spring.cloud.nacos.discovery.ip = 本机公网IP spring.cloud.nacos.discovery.port = 服务端口
- 从xml读取gps数据获取经纬高
#!/usr/bin/python # -*- coding: UTF-8 -*- from xml.dom.minidom import parse import xml.dom.minidom & ...
- java图形化界面编程(AWT)
1.AWT编程简介 在JDK发布时,sun公司提供了一套基本的GUI类库,这个GUI类库希望可以在所有平台下都能运行,这套基本类库被称为"抽象窗口工具集",它为java应用程序提供 ...
- net-snmp 自定义OID利用脚本获取值
两种办法: 1)pass方式 /etc/snmp/snmpd.conf 写脚本 脚本需要注意:要连续输出三行:1.OID 2.类型 3.值 如果不按照这个规定,直接输出值,将会报错. 检查 第二种方法 ...
- gulp技术:自动化构建工具
作用:压缩css.js.img,合并文件,改名字,编译sass,拷贝 使用步骤: 1.安装node环境,下一步,下一步,安装C盘: 2.在你的根目录下,在地址栏输入cmd回车: 3.检测node和np ...
- ubuntu通过ftp向小米手机传输多个文件
输入ftp命令,连接手机 root@wanboo-Inspiron-5570:~# ftp 192.168.1.104 2121 Connected to 192.168.1.104. 220 Swi ...
- 【Unity】拖动图片生成对应Image
写在前面 拼UI时会用到多个Image,一般操作是:①新建一个Image,②拖入Image用到的图片,③SetNativeSize,④关闭不必要的raycastTarget .为了能尽快拼完UI,我写 ...