AbstractQueuedSynchronizer(十四)——应用之FutureTask

前面看过了很多利用AbstractQueuedSynchronizer做的二次开发,主要是针对锁的获取和释放以及状态的读取和变更做的一系列变化。

FutureTask和guava中的AbstractFuture很像,后者用一系列的set方法来设置值或异常来触发锁的释放。而FutureTask通过构造一个task任务,并用该任务的完成,用任务的返回值来设置future的value并触发锁的释放。

1.RunnableFuture

FutureTask实现了RunnableFuture接口,该接口组合了Runnable和Future两个接口,

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的时候传入一个Callable,
public class FutureTask<V> implements RunnableFuture<V> {
    /**
     * Creates a <tt>FutureTask</tt> that will, upon running, execute the
     * given <tt>Callable</tt>.
     *
     * @param  callable the callable task
     * @throws NullPointerException if callable is null
     */
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        sync = new Sync(callable);
    }
    ...
}
实现Runnable接口的run方法,

/**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    public void run() {
        sync.innerRun();
    }

2.innerRun
void innerRun() {
            if (!compareAndSetState(READY, RUNNING))
                return;

            runner = Thread.currentThread();
            if (getState() == RUNNING) { // recheck after setting thread
                V result;
                try {
                    result = callable.call();
                } catch (Throwable ex) {
                    setException(ex);
                    return;
                }
                set(result);
            } else {
                releaseShared(0); // cancel
            }
        }
innerRun方法在FutureTask实现Runnable的run方法中执行,执行成功的话会把callable的返回值set到future的value中,如果抛出异常就设置异常,不管结果如何都会释放锁。

这里有double check,在原子设置状态从READY到RUNNING之后,还要在check一下现在的状态是否是RUNNING,防止调用了对外提供的public方法cancel,

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

boolean innerCancel(boolean mayInterruptIfRunning) {
            for (;;) {
                int s = getState();
                if (ranOrCancelled(s))
                    return false;
                if (compareAndSetState(s, CANCELLED))
                    break;
            }
            if (mayInterruptIfRunning) {
                Thread r = runner;
                if (r != null)
                    r.interrupt();
            }
            releaseShared(0);
            done();
            return true;
        }
innerCancel方法会把正在运行的(状态是RUNNING)的task取消掉,所以要double check一下,如果被取消了,innerRun什么都不做,直接释放锁。

3.runAndReset可重用任务

/**
     * Executes the computation without setting its result, and then
     * resets this Future to initial state, failing to do so if the
     * computation encounters an exception or is cancelled.  This is
     * designed for use with tasks that intrinsically execute more
     * than once.
     * @return true if successfully run and reset
     */
    protected boolean runAndReset() {
        return sync.innerRunAndReset();
    }
boolean innerRunAndReset() {
            if (!compareAndSetState(READY, RUNNING))
                return false;
            try {
                runner = Thread.currentThread();
                if (getState() == RUNNING)
                    callable.call(); // don't set result
                runner = null;
                return compareAndSetState(RUNNING, READY);
            } catch (Throwable ex) {
                setException(ex);
                return false;
            }
        }
这里如果调用reset方法,执行任务但不设置value,然后把所有状态reset到初始状态。

4.执行task的线程runner
每次释放锁的时候,都会把该runner置位null,在innerIsDone方法中同时通过state和runner的值来判断任务是否完成。
/**
         * Implements AQS base release to always signal after setting
         * final done status by nulling runner thread.
         */
        protected boolean tryReleaseShared(int ignore) {
            runner = null;
            return true;
        }
boolean innerIsDone() {
            return ranOrCancelled(getState()) && runner == null;
        }
5.扩展FutureTask——ListenableFutureTask

增加了guava的ListenableFuture的addListener的属性。

通过覆写FutureTask提供的done()方法来完成附加的操作,比如这里执行添加的listener的操作。

/**
     * Protected method invoked when this task transitions to state
     * <tt>isDone</tt> (whether normally or via cancellation). The
     * default implementation does nothing.  Subclasses may override
     * this method to invoke completion callbacks or perform
     * bookkeeping. Note that you can query status inside the
     * implementation of this method to determine whether this task
     * has been cancelled.
     */
    protected void done() { }
/**
   * Internal implementation detail used to invoke the listeners.
   */
  @Override
  protected void done() {
    executionList.execute();
  }
该done方法在通过set或者cancel方法成功,并释放了锁之后会调用。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值