Java FutureTask类使用案例解析

FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提空 start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果。结果只可以在计算完成之后获取,get方法会阻塞当计算没有完成的时候,一旦计算已经完成,那么计算就不能再次启动或是取消。

一个FutureTask 可以用来包装一个 Callable 或是一个runnable对象。因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit)给一个Excutor执行(excution).

FutureTask是java 5引入的一个类,从名字可以看出来FutureTask既是一个Future,又是一个Task。

我们看下FutureTask的定义:

public class FutureTask<V> implements RunnableFuture<V> {
  ...
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
  /**
   * Sets this Future to the result of its computation
   * unless it has been cancelled.
   */
  void run();
}

FutureTask实现了RunnableFuture接口,RunnableFuture接口是Runnable和Future的综合体。

作为一个Future,FutureTask可以执行异步计算,可以查看异步程序是否执行完毕,并且可以开始和取消程序,并取得程序最终的执行结果。

除此之外,FutureTask还提供了一个runAndReset()的方法, 该方法可以运行task并且重置Future的状态。

Callable和Runnable的转换
我们知道Callable是有返回值的,而Runnable是没有返回值的。
Executors提供了很多有用的方法,将Runnable转换为Callable:

  public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
      throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
  }

FutureTask内部包含一个Callable,并且可以接受Callable和Runnable作为构造函数:

  public FutureTask(Callable<V> callable) {
    if (callable == null)
      throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;    // ensure visibility of callable
  }
  public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;    // ensure visibility of callable
  }

它的内部就是调用了Executors.callable(runnable, result);方法进行转换的。

以Runnable运行

既然是一个Runnable,那么FutureTask就可以以线程的方式执行,我们来看一个例子:

@Test
  public void convertRunnableToCallable() throws ExecutionException, InterruptedException {
    FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
      @Override
      public Integer call() throws Exception {
        log.info("inside callable future task ...");
        return 0;
      }
    });

    Thread thread= new Thread(futureTask);
    thread.start();
    log.info(futureTask.get().toString());
  }

上面例子是以单个线程来执行的,同样我们也可以将FutureTask提交给线程池来执行:

  @Test
  public void workWithExecutorService() throws ExecutionException, InterruptedException {
    FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
      @Override
      public Integer call() throws Exception {
        log.info("inside futureTask");
        return 1;
      }
    });
    ExecutorService executor = Executors.newCachedThreadPool();
    executor.submit(futureTask);
    executor.shutdown();
    log.info(futureTask.get().toString());
  }

本文的例子可参考https://github.com/ddean2009/learn-java-concurrency/tree/master/futureTask

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 比较java中Future与FutureTask之间的关系

    Future与FutureTask都是用于获取线程执行的返回结果.下面我们就对两者之间的关系与使用进行一个大致的介绍与分析 一.Future与FutureTask介绍: Future位于java.util.concurrent包下,它是一个接口 public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() t

  • 简谈java并发FutureTask的实现

    概述 在使用java多线程解决问题的时候,为了提高效率,我们常常会异步处理一些计算任务并在最后异步的获取计算结果,这个过程的实现离不开Future接口及其实现类FutureTask.FutureTask类实现了Runnable, Future接口,接下来我会通过源码对该类的实现进行详解. 使用 我们先看下FutureTask中的主要方法如下,可以看出FutureTask实现了任务及异步结果的集合功能.看到这块的方法,大家肯定会有疑问,Runnable任务的run方法返回空,FutureTask如

  • Java中Future、FutureTask原理以及与线程池的搭配使用

    Java中的Future和Future通常和线程池搭配使用,用来获取线程池返回执行后的返回值.我们假设通过Executors工厂方法构建一个线程池es ,es要执行某个任务有两种方式,一种是执行 es.execute(runnable) ,这种情况是没有返回值的: 另外一种情况是执行 es.submit(runnale)或者 es.submit(callable) ,这种情况会返回一个Future的对象,然后调用Future的get()来获取返回值. Future public interfac

  • java多线程编程同步器Future和FutureTask解析及代码示例

    publicinterfaceFuture<V>Future表示异步计算的结果.它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果.计算完成后只能使用get方法来获取结果,如有必要,计算完成前可以阻塞此方法.取消则由cancel方法来执行.还提供了其他方法,以确定任务是正常完成还是被取消了.一旦计算完成,就不能再取消计算.如果为了可取消性而使用Future但又不提供可用的结果,则可以声明Future<?>形式类型.并返回null作为底层任务的结果. Future主要

  • Java线程池FutureTask实现原理详解

    前言 线程池可以并发执行多个任务,有些时候,我们可能想要跟踪任务的执行结果,甚至在一定时间内,如果任务没有执行完成,我们可能还想要取消任务的执行,为了支持这一特性,ThreadPoolExecutor提供了 FutureTask 用于追踪任务的执行和取消.本篇介绍FutureTask的实现原理. 类视图 为了更好的理解FutureTask的实现原理,这里先提供几个重要接口和类的结构,如下图所示: RunnableAdapter ThreadPoolExecutor提供了submit接口用于提交任

  • java多线程返回值使用示例(callable与futuretask)

    Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值,下面来看一个简单的例子 复制代码 代码如下: package com.future.test; import java.io.FileNotFoundException;import java.io.IOException;i

  • Java中的Runnable,Callable,Future,FutureTask的比较

    Java中的Runnable,Callable,Future,FutureTask的比较 Java中存在Runnable.Callable.Future.FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别. Runnable 其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中, 该函数没有返回值 .然后使用某个线程去执行该runnable即可实现多线程,Thread类在调

  • Java FutureTask类使用案例解析

    FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提空 start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果.结果只可以在计算完成之后获取,get方法会阻塞当计算没有完成的时候,一旦计算已经完成,那么计算就不能再次启动或是取消. 一个FutureTask 可以用来包装一个 Callable 或是一个runnable对象.因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit

  • Java对象创建内存案例解析

    Java对象创建内存图解析 1. 栈 Java栈的区域很小 , 特点是存取的速度特别快,栈存储的特点是, 先进后出,存储速度快的原因: 栈内存, 通过 栈指针'来创建空间与释放空间,指针向下移动, 会创建新的内存, 向上移动, 会释放这些内存.这种方式速度特别快 , 仅次于PC寄存器,但是这种移动的方式, 必须要明确移动的大小与范围 ,明确大小与范围是为了方便指针的移动 , 这是一个对于数据存储的限制, 存储的数据大小是固定的 , 影响了程序的灵活性. 所以我们把更大部分的数据 存储到了堆内存中

  • java操作elasticsearch的案例解析

    这篇文章主要介绍了java操作elasticsearch的案例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 到目前为止,我们一直都是使用RESTful风格的 API操作elasticsearch服务,但是通过我们之前的学习知道,elasticsearch提供了很多语言的客户端用于操作elasticsearch服务,例如:java.python..net.JavaScript.PHP等.而我们此次就学习如何使用java语言来操作elasti

  • Java Calendar类使用案例详解

    在实际项目当中,我们经常会涉及到对时间的处理,例如登陆网站,我们会看到网站首页显示XXX,欢迎您!今天是XXXX年....某些网站会记录下用户登陆的时间,比如银行的一些网站,对于这些经常需要处理的问题,Java中提供了Calendar这个专门用于对日期进行操作的类,那么这个类有什么特殊的地方呢,首先我们来看Calendar的声明 public abstract class Calendar extends Objectimplements Serializable, Cloneable, Com

  • Java Number类原理实例解析

    这篇文章主要介绍了Java Number类原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Number类 内置数据类型:byte.int.long.double等 包装类:Integer.Long.Byte.Double.Float.Short. ​ 这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类.相似的,编译器也可以把一个对象拆箱为内置类型.Number 类属于 java.l

  • java反射耗时测试案例解析

    java反射相对与普通的对象调用原理上来说更加耗时,在调用次数较少的情况下可忽略性能损失,但当调用次数非常多时,需要考虑到此问题,即调用次数过多时不宜使用反射,以下举例: package com.test.reflection; import java.lang.reflect.Method; public class ReflectionDemo { public static void main(String[] args) throws Exception { // 常规方式 Studen

  • java继承的概念及案例解析

    这篇文章主要介绍了java继承的概念及案例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 package java09; //定义一个员工类 public class Employee { public void method(){ System.out.println("方法执行!!!"); } } package java09; //定义一个教师类 public class Teacher extends Employee {

  • Java线程的并发工具类实现原理解析

    目录 一.fork/join 1. Fork-Join原理 2. 工作窃取 3. 代码实现 二.CountDownLatch 三.CyclicBarrier 四.Semaphore 五.Exchange 六.Callable.Future.FutureTask 在JDK的并发包里提供了几个非常有用的并发工具类.CountDownLatch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线程间交换数据的一种手段.本章会配合一些应

  • java.lang.Void类源码解析

    在一次源码查看ThreadGroup的时候,看到一段代码,为以下: /* * @throws NullPointerException if the parent argument is {@code null} * @throws SecurityException if the current thread cannot create a * thread in the specified thread group. */ private static Void checkParentAcc

  • JAVA StringBuffer类与StringTokenizer类代码解析

     StringBuffer类提供了一个字符串的可变序列,类似于String类,但它对存储的字符序列可以任意修改,使用起来比String类灵活得多.它常用的构造函数为: StringBuffer() 构造一个空StringBuffer对象,初始容量为16个字符. StringBuffer(Stringstr) 构造一个StringBuffer对象,初始内容为字符串str的拷贝. 对于StringBuffer类,除了String类中常用的像长度.字符串截取.字符串检索的方法可以使用之外,还有两个较为

随机推荐