FutureTask和Callable源码解析

通过Future和Callable可以实现异步计算框架,实现流程如下:

1、实现Callable接口里的call方法。2、FutureTask(Callable<V> callable)new FutureTask 3、Thread(FutureTask ).start启动线程4、FutureTask的get()方法阻塞式得到结果。

二、源码分析

//通过下面可以看到:FutureTask实现了Runnable接口和Future接口,所有可以和Runnable接口一样被Thread进行启动。(其实Thread也实现了Runnable接口)

public class FutureTask<V> implements RunnableFuture<V> {

public interface RunnableFuture<V> extends Runnable, Future<V> {

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        sync = new Sync(callable);//Sync为继承的AQS队列
    }

    public void run() {//通过FutureTask的run包装了Callable里的call方法的执行,start启动调用该方法
        sync.innerRun();
    }

    public V get() throws InterruptedException, ExecutionException {
        return sync.innerGet();
    }

    public boolean cancel(boolean mayInterruptIfRunning) {
        return sync.innerCancel(mayInterruptIfRunning);
    }

------------------------------------------------------------------------------------------------------------------------------------------------------------------

    private final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -7828117401763700385L;


        /** State value representing that task is running */
        private static final int RUNNING   = 1;
        /** State value representing that task ran */
        private static final int RAN       = 2;
        /** State value representing that task was cancelled */
        private static final int CANCELLED = 4;

        /** The underlying callable */
        private final Callable<V> callable;
        /** The result to return from get() */
        private V result;
        /** The exception to throw from get() */
        private Throwable exception;


        /**
         * The thread running task. When nulled after set/cancel, this
         * indicates that the results are accessible.  Must be
         * volatile, to ensure visibility upon completion.必须是volatile确保线程完成后的可见性
         */
        private volatile Thread runner;

        void innerRun() {
            if (!compareAndSetState(0, RUNNING))
                return;
            try {
                runner = Thread.currentThread();
                if (getState() == RUNNING) // recheck after setting thread因为没有加锁进行多次检查
                    innerSet(callable.call());//调用call方法完成执行任务
                else
                    releaseShared(0); // cancel
            } catch (Throwable ex) {
                innerSetException(ex);
            }
        }



        void innerSet(V v) {
    for (;;) {
int s = getState();
if (s == RAN)
    return;
                if (s == CANCELLED) {
    // aggressively release to set runner to null,
    // in case we are racing with a cancel request
    // that will try to interrupt runner
                    releaseShared(0);//直接唤醒阻塞等待获取结果的线程队列
                    return;
                }
if (compareAndSetState(s, RAN)) {//修改为执行完成状态
                    result = v;//赋值任务结果,普通私有变量,如何确保其他线程的可见性?
                    releaseShared(0);//其中会涉及到volatile runner变量的写入,确保了result的结果借助 volatile的写同步到主内存
                    done();
    return;
                }
            }
        }


        protected int tryAcquireShared(int ignore) {
            return innerIsDone()? 1 : -1;//在RAN | CANCELLED状态返回1,进入到唤醒阻塞的结果线程队列
        }


        boolean innerIsDone() {
            return ranOrCancelled(getState()) && runner == null;
        }

        private boolean ranOrCancelled(int state) {
            return (state & (RAN | CANCELLED)) != 0;
        }

        protected boolean tryReleaseShared(int ignore) {
            runner = null;//其中会涉及到volatile runner变量的写入
            return true;
        }

总结:Future表示任务的所有操作将在Future.get中返回之前执行。run方法通过对volite变量的写入确保之前的结果result写入都存储会主内存,通过在get方法里对volatile state变量的读取,确保了线程工作内存加载了最新的主内存信息。使result得以在不同的线程之间进行传递

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值