Java多线程编程(三)-Future、FutureTask、CompletableFuture

本文详细介绍了Java多线程编程中的Future模式,讲解了Future接口的基本概念和执行原理,接着深入探讨了FutureTask的实现,包括其内部变量、run()方法、get()方法和cancel()方法的工作流程。最后,文章分析了CompletableFuture的引入原因,总结了CompletableFuture的主要特性,如异步执行、结果转换和组合操作,并对比了Future、FutureTask和CompletableFuture的差异。
摘要由CSDN通过智能技术生成

一、Future模式

1.Future简介

    Future本身是一种被广泛运用的开发设计模式,在很大程度上简化需要数据流同步的并发应用开发。Future对象本身可以看做是一个显示的引用,他的核心思想是异步调用,类似于ajax的异步请求,无需等待请求的结果,可以继续去处理其他的业务。

    例如就像现在在网上买东西,选中东西付款之后,不会立即拿到东西,而是拿到一个买东西的订单号,然后过一段时间之后根据订单号去拿真正的货物,而在等待货物的期间我们是可以去干别的任何事情。其中Future接口就是订货单,真正处理订单的是Executor类,他根据Future接口的要求来生产产品。

2.Future接口

    下面是Future接口中的定义的方法,包括5个接口方法,这5个接口方法实际上提供了Future的3个功能:判断任务是否完成,中断任务,获取任务的执行结果。

public interface Future<V> {

	/**
	 * 取消任务的执行
	 * 如果任务已经完成,或者已经被取消,或者因为其他原因不能被取消,则返回失败
	 * 如果任务在调用时还未启动,那么返回成功
	 * 如果任务已经在执行过程中,则根据参数确定此执行任务的线程能否被中断,来试图停止任务的执行
	 * @param mayInterruptIfRunning
	 * @return
	 */
    boolean cancel(boolean mayInterruptIfRunning);

    /**
     * 判断任务是否已经取消,任务正常完成前将其取消,则返回true
     * @return
     */
    boolean isCancelled();

    /**
     * 判断任务是否已经完成,需要注意的是如果任务正常、异常或取消,都返回true
     * @return
     */
    boolean isDone();

    /**
     * 等待任务执行结束,并返回结果
     * @return
     * @throws InterruptedException  线程被中断异常
     * @throws ExecutionException 任务执行异常
     */
    V get() throws InterruptedException, ExecutionException;

    /**
     * 等待任务执行结束,并返回结果,同上面get方法的区别是设置了超时时间,
     * @param timeout
     * @param unit
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     * @throws TimeoutException
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

3.Future模式执行的原理


角色 作用
main 启动系统的主程序,调用client发送请求
client 返回Data对象,并且立即返回FutureData结果 ,同时开启ClientThread线程来装配RealData
Data 返回数据的接口
FutureData client请求之后立即返回的一个“虚假”的结果
RealData 真实的结果数据


二、FutureTask实现

1.FutureTask介绍

    Future只是一个接口,无法直接创建对象,因此有了FutureTask。RunnableFuture继承了Runnable和Future接口,而FutureTask实现了RunnableFuture接口。

public class FutureTask<V> implements RunnableFuture<V> {
	……
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

2.FutureTask中的变量

/**
     * state状态变化的方式
     * 1.正常完成的流程:NEW -> COMPLETING -> NORMAL
     * 2.出现异常的流程:NEW -> COMPLETING -> EXCEPTIONAL
     * 3.被取消:NEW -> CANCELLED
     * 4.被中断:NEW -> INTERRUPTING -> INTERRUPTED
     */
	//记录task的状态
    private volatile int state;
    //新建,也表示内部成员callable已成功赋值,一直到工作线程完成FutureTask中的run()
    private static final int NEW          = 0;
    //执行中,工作线程在处理task时的中间状态,处于该状态是,说明工作线程正准备设置result
    private static final int COMPLETING   = 1;
    //正常,设置result结果完成,FutureTask处于该状态,代表过程结果,该状态为正确完成的最终状态
    private static final int NORMAL       = 2;
    //异常:task在指向过程中出现异常,也是最终态
    private static final int EXCEPTIONAL  = 3;
    //取消:task被取消,最终态
    private static final int CANCELLED    = 4;
    //中断中:task运行过程中被中断时,设置的中间状态
    private static final int INTERRUPTING = 5;
    //被中断:中断完成的最终状态
    private static final int INTERRUPTED  = 6;

    //具体run()运行时会调用其方法call(),并获取结果,结束执行置为null
    private Callable<V> callable;
    //伴随state进行读写
    private Object outcome;
    //具体的工作线程
    private volatile Thread runner;
    //并发stack数据结构,用于存放阻塞在该FutureTask.get方法的线程  Treiber算法参考Lock-Free算法
    private volatile WaitNode waiters;

2.FutureTask的run()方法

    下面是FutureTask的run()方法的执行过程,主要分为几个步骤:

    (1)判断当前任务的状态,如果任务的状态不是new,说明状态已经发生了变化,执行的路径是上面4种中的一种,直接返回。

    (2)如果工作线程是null,则把当前执行任务的线程赋值给runner,如果runner不为null,说明已经有线程在执行,直接返回。此处使用compareAndSwapObject来对工作线程进行赋值,是因为该方法能够保证原子性,保证多个线程同时提交一个FutureTask时,确保该FutureTask的run只被调用一次,如果想运行多次,使用runAndReset()方法。

    (3)开始执行任务,如果执行的任务不为空,并且任务的状态是new,调用Callable的call方法。

    (4)

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值