Future接口介绍

  Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。

  Future 一般由 ExecutorService 的submit()、invokeAll()方法返回的,用于跟踪、获取任务在线程池中的运行情况、等待运算结果,还可以取消任务。(还有其子接口 ScheduleFuture 则由 ScheduleExecutorService 的schedule()等方法返回);

方法描述

boolean cancel(boolean mayInterruptIfRunning):

试图取消对此任务的执行。分成以下三种情况:

  • 如果任务尚未启动,则此任务将永不运行。
  • 如果任务已经启动,则 mayInterruptIfRunning 参数确定是否 中断这个任务来尝试停止任务。同时,任务也应该要对中断敏感。
  • 任务已完成、或已取消,或者由于某些其他原因而无法取消,返回false。

注意: 此方法返回后,对 isDone() 的后续调用将始终返回 true。但如果此方法返回 true,则对 isCancelled() 的后续调用才将始终返回

boolean isCancelled(): 如果在任务正常完成前将其取消,则返回 true。

boolean isDone(): 如果任务已完成,则返回 true。 可能由于正常终止、异常或取消而完成,在所有这些情况中,此方法都将返回 true。

获取计算结果

  获取计算结果的方法,JDK提供了两个方法:阻塞获取 与 超时等待获取。这两个方法会抛出 CancellationException(任务被取消时)、InterruptedException

V get(): 等待计算完成,然后获取其结果。

V get(long timeout,TimeUnit unit): 最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。

@ Example 示例

  下面的例子,是在单线程的线程池中提交两个任务(任务A、任务B)。

public class Test {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//单线程的线程池
ExecutorService executor = Executors.newSingleThreadExecutor();
//提交两个任务
Future futureA = executor.submit(new MyCallable("futureA"));
Future futureB = executor.submit(new MyCallable("futureB")); Thread.sleep(1000);
//在运行一秒后,判断任务A是否完成
if(futureA.isDone()){
//如果完成,则直接获取结果
double result = (double) futureA.get();
System.out.println("运算结果是:"+result);
}else{
//如果没有完成,则取消任务A
boolean b = futureA.cancel(false);
System.out.println("futureA 执行了cancel方法,返回的值是:"+b);
}
//取消任务B
futureB.cancel(false);
}
} class MyCallable implements Callable{ String taskName; public MyCallable(String taskName){
this.taskName = taskName;
} @Override
public Object call() {
try {
//模拟任务的执行时间为 2s
for(int i=0;i<5;i++){
Thread.sleep(400);
System.out.println(taskName+"任务正在运行中.....");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
double d = Math.random() * 10;
return d;
}
}

运行结果:

futureA任务正在运行中.....

futureA任务正在运行中.....

futureA 执行了cancel方法,返回的值是:true

futureA任务正在运行中.....

futureA任务正在运行中.....

futureA任务正在运行中.....

  任务A是在执行时被取消的,调用的cancel(false) 方法返回的结果为true,但是任务并没有真的停止执行。任务B则是在还没被执行时取消的,所以任务B在后续的时间内,没有执行。

  可以得出结论,cancel( false)方法是取消尚未被执行的任务、周期任务,而不是停止正在执行的任务。当然,如果想要停止正在执行的任务,任务里面必须是中断敏感,然后 cancel(true),参数为true,即在cancel的同时,也发出中断信号。

//简单的中断处理,发现中断退出
public void run(){
while(!Thread.interrupted()){
//.....
}
}

FutureTask 介绍

  FutureTask 是一个可取消的异步计算任务,是一个独立的类,实现了 Future、Runnable接口。FutureTask 的出现是为了弥补 Thread 的不足而设计的,可以让程序员跟踪、获取任务的执行情况、计算结果

  因为 FutureTask 实现了 Runnable,所以 FutureTaskk 可以作为参数来创建一个新的线程来执行,也可以提交给 Executor 执行。FutureTask 一旦计算完成,就不能再重新开始或取消计算。

构造方法

FutureTask(Callable callable)

创建一个 FutureTask,一旦运行就执行给定的 Callable。

FutureTask(Runnable runnable, V result)

创建一个 FutureTask,一旦运行就执行给定的 Runnable,并安排成功完成时 get 返回给定的结果 。

应用场景

FutureTask 可用于异步获取执行结果或可以取消执行任务的场景;

@ Example 简单例子

  下面的例子中,因为计算数据的时间比较长,所以main线程就额外起一个异步线程来计算数据,从而使得计算数据的同时,main线程可以做其他工作,直到需要用到计算结果时,才去获取计算结果。

  需要注意的是,线程 thread2 并没有执行 FutureTask,因为 FutureTask 已经在线程 thread 中完成了。一旦 FutureTask 计算完成,就不能再重新开始或取消计算。

public class Test {
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Double> task = new FutureTask(new MyCallable());
//创建一个线程,异步计算结果
Thread thread = new Thread(task);
thread.start();
//主线程继续工作
Thread.sleep(1000);
System.out.println("主线程等待计算结果...");
//当需要用到异步计算的结果时,阻塞获取这个结果
Double d = task.get();
System.out.println("计算结果是:"+d); //用同一个 FutureTask 再起一个线程
Thread thread2 = new Thread(task);
thread2.start();
}
} class MyCallable implements Callable<Double>{ @Override
public Double call() {
double d = 0;
try {
System.out.println("异步计算开始.......");
d = Math.random()*10;
d += 1000;
Thread.sleep(2000);
System.out.println("异步计算结束.......");
} catch (InterruptedException e) {
e.printStackTrace();
}
return d;
}
}

运行结果:

异步计算开始.......

主线程等待计算结果...

异步计算结束.......

计算结果是:1002.7806590582911

除了实现Future、Runnable外,此类还提供了几个protected方法,用于扩展此类

protected void done()

当此任务转换到状态 isDone(不管是正常地还是通过取消)时,调用受保护的方法。默认实现不执行任何操作。

protected void set(V v)

除非已经设置了此 Future 或已将其取消,否则将其结果设置为给定的值。在计算成功完成时通过 run 方法内部调用此方法。

protected void setException(Throwable t)

除非已经设置了此 Future 或已将其取消,否则它将报告一个 ExecutionException,并将给定的 throwable 作为其原因。在计算失败时通过 run 方法内部调用此方法。

protected boolean runAndReset()

执行计算而不设置其结果,然后将此 Future 重置为初始状态,如果计算遇到异常或已取消,则该操作失败。本操作被设计用于那些本质上要执行多次的任务。

Executor框架(七)Future 接口、FutureTask类的更多相关文章

  1. java并发编程-Executor框架 + Callable + Future

    from: https://www.cnblogs.com/shipengzhi/articles/2067154.html import java.util.concurrent.*; public ...

  2. java集合框架部分相关接口与类的介绍

    集合基础 接口 Iterable //Implementing this interface allows an object to be the target of the "for-ea ...

  3. Java学习笔记33(集合框架七:Collections工具类)

    数组有工具类,方面操作数组 集合也有工具类:Collections 常用方法示例: package demo; import java.util.ArrayList; import java.util ...

  4. java多线程系列(七)---Callable、Future和FutureTask

    Callable.Future和FutureTask 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量 ...

  5. 详解Executor框架

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

  6. Executor框架学习笔记

    Java中的线程即是工作单元也是执行机制,从JDK 5后,工作单元与执行机制被分离.工作单元包括Runnable和Callable,执行机制由JDK 5中增加的java.util.concurrent ...

  7. Java 线程池 Executor 框架

    在Java中,可以通过new Thread 的方法来创建一个新的线程执行任务,但是线程的创建是非常耗时的,而且创建出来的新的线程都各自运行.缺乏统一的管理,这样的后果是可能导致创建过多的线程从而过度消 ...

  8. Executor框架(一)Executor框架介绍

    Executor框架简介 Executor框架的两级调度模型   在HotSpot VM的线程模型中,Java线程被一对一映射为本地操作系统线程.Java线程启动时会创建一个本地操作系统线程:当Jav ...

  9. 【Java多线程】Executor框架的详解

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

  10. 第十章 Executor框架

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

随机推荐

  1. TX2-start 6 CPU kernel-开启高功耗模式

    1.TX2简介 Jetson TX2是由一个GPU和一个CPU集群组成.CPU集群由双核denver2处理器和四核ARM Cortex-A57组成,通过高性能互连架构连接.拥有6个CPU核心和一个GP ...

  2. React中如何优雅的捕捉事件错误

    React中如何优雅的捕捉事件错误 前话 人无完人,所以代码总会出错,出错并不可怕,关键是怎么处理. 我就想问问大家react的错误怎么捕捉呢? 这个时候: 小白:怎么处理? 小白+: ErrorBo ...

  3. java8 array、list操作 汇【3】)(-Java8新特性之Collectors 详解

    //编写一个定制的收集器 public static class MultisetCollector<T> implements Collector<T, Multiset<T ...

  4. python 直接将list 整体转化-----------map()

    假设有这样一个 results = ['1', '2', '3'] 转化为下面这个样子 results = [1, 2, 3] 我们可以使用map函数 在Python2中这样操作: results = ...

  5. day41 mysql 学习 练习题 重要*****

    MySQL 练习题[二1.表如下: 收获和注意点:***** #1 GROUP by 可以放到where s_id in ()条件局后边 GROUP BY s_id having 详见题12 #2 做 ...

  6. memsql 6.7集群安装

    预备环境处理 安装yum 源 yum install -y yum-utils yum-config-manager --add-repo https://release.memsql.com/pro ...

  7. baidu手机浏览器安卓4.5版公布:由于快,所以爱

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDUyMzk4OA==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  8. JMeter分布式部署的大致步骤以及误区解释

    master和slave机要在同一网段内,才能做分布式(Jmeter要配环境变量,这样不用手动起server) 分布式不成功,解决方案: 1.master端和slave端要ping通 2.ping通后 ...

  9. [C#]画图全攻略(饼图与柱状图)(转)

    http://blog.chinaunix.net/uid-15481846-id-2769484.html 首先建立一个c#的类库.   打开vs.net,建立一个名为Insight_cs.WebC ...

  10. POJ3613 k边最短路

    题目:http://poj.org/problem?id=3613 Floyd求最短路的实质是矩阵的自乘.( i , k )是第 i 行第k列,( k , j )是第k行第 j 列:用它们的max更新 ...