java中Future的实现原理

执行结果是如何通过Future返回的

首先我们通过一段代码来看看我们拿到的future对象到底是个什么
上代码:

package com.jswdwsx;

import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FutureStudy {

    public static void main(String[] args) {
        Future<Integer> f = Executors.newSingleThreadExecutor().submit(() -> 1);
		// 打印返回的future对象的具体类
        System.out.println(f.getClass());
    }
}

输出如下

class java.util.concurrent.FutureTask

由运行结果可以看出我们拿到的Future对象的具体类是FutureTask。
那么我们基于JDK1.8看FutureTask中get方法的实现:

    /**
     * @throws CancellationException {@inheritDoc}
     */
    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    /**
     * @throws CancellationException {@inheritDoc}
     */
    public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
            throw new TimeoutException();
        return report(s);
    }

report方法如下:

    /**
     * Returns result or throws exception for completed task.
     *
     * @param s completed state value
     */
    @SuppressWarnings("unchecked")
    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

总的来说就是根据state变量判断任务是否执行完成(包括正常和异常),如果未完成就等,正常完成就返回结果,其他情况抛出对应异常。这里的结果—— outcome从何而来,下一节分析。

Callable是如何被执行的

我们知道Thread只能执行实现了Runnable接口的任务,那么Callable是如何被执行的呢?
我们可以查看submit方法源码,这个submit方法是在ExecutorService接口中声明的,在AbstractExecutorService抽象类中实现的。
几个关键类的继承体系
上代码:

    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

可以看到在submit方法中以task为参数构造了一个FutureTask对象,然后以此为参数调用execute方法,最后返回该对象。
看到这里我们可以敏锐地察觉到,这个FutureTask类,必然同时实现Runnable接口和Future接口。因为它作为execute方法的参数,而execute方法只接收Runnable对象;同时它作为submit方法的返回值,而submit方法的返回值就是一个Future对象。
继续看FutureTask类源码:

public class FutureTask<V> implements RunnableFuture<V> {
	
	//...省略其他
	private volatile int state;
	private Callable<V> callable;
    private Object outcome;
    private volatile Thread runner;
    
    // 构造方法需要一个Callable作为执行的内容
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
    
    public void run() {
    	// 如果判断状态不是NEW 或者 通过一次CAS设置当前线程为本任务的执行线程失败
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                	// 这里执行callable的call方法,之后result会被赋值给outcome
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
    protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        	// 这里通过自旋给outcome赋值,回答了上一节最后的问题
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
			// 唤醒其他等待线程,并清空等待队列,做一些后续处理工作,就不进去细看了
            finishCompletion();
        }
    }
    //...省略其他(包括前面看过的get和report方法)
}

RunnableFuture接口源码:

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两个接口。
再看上面FutureTask的run方法,就是执行了通过构造参数参数传入的Callable对象的call方法,并把结果赋值给outcome变量。
所以Thread是执行了FutureTask的run方法,而FutureTask的run方法执行了Callable的call方法。

总结Callable任务的执行流程

可以看到FutureTask类在Callable任务的执行中扮演着十分重要的角色,正是FutureTask将三个关键的部分联系起来:

  • Callable接口(作为构造方法的参数和成员变量)
  • Runnable接口(间接实现)
  • Future接口(间接实现)

至此我们可以梳理出Callable任务的执行流程:

  1. 我们通过实现Callable接口定义一个带返回值的任务
  2. 通过线程池submit方法提交Callable对象
  3. submit方法构造FutureTask交给线程池执行,同时返回FutureTask用于结果的获取
  4. 线程池将FutureTask交给线程执行
  5. 线程执行FutureTask的run方法
  6. FutureTask的run方法执行Callable对象的call方法,并将结果保存在outcome中
  7. 我们通过返回的FutureTask获取outcome中执行结果
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值