AbstractQueuedSynchronizer(十二)——应用之AbstractFuture

 和CountDownLatch一样,这也是利用共享模式的AbstractQueuedSynchronizer来进行扩展的功能。

1.覆写的tryAcquireShared方法

/*
     * Acquisition succeeds if the future is done, otherwise it fails.
     */
    @Override
    protected int tryAcquireShared(int ignored) {
      if (isDone()) {
        return 1;
      }
      return -1;
    }

通过isDone方法判断,如果没有完成,阻塞,可以获得锁。和CountDownLatch类似,后者是判断getState是否是0,state是int型,所以可以有多个状态,对应了多次countDown。

这里isDone返回值是boolean型,所以只有两个状态,完成/没完成。

/**
     * Checks if the state is {@link #COMPLETED}, {@link #CANCELLED}, or {@link
     * INTERRUPTED}.
     */
    boolean isDone() {
      return (getState() & (COMPLETED | CANCELLED | INTERRUPTED)) != 0;
    }

但实际没完成有多种情况,如代码所示,COMPLETED,CANCELLED和INTERRUPTED都是完成状态,所以只要是这三种状态之一,都表示完成,可以获得锁。

2.覆写的tryReleaseShared

/*
     * We always allow a release to go through, this means the state has been
     * successfully changed and the result is available.
     */
    @Override
    protected boolean tryReleaseShared(int finalState) {
      setState(finalState);
      return true;
    }

该方法永远返回true,触发该方法的条件就是调用complete方法中的releaseShared方法。

3.complete方法

/**
     * Implementation of completing a task.  Either {@code v} or {@code t} will
     * be set but not both.  The {@code finalState} is the state to change to
     * from {@link #RUNNING}.  If the state is not in the RUNNING state we
     * return {@code false} after waiting for the state to be set to a valid
     * final state ({@link #COMPLETED}, {@link #CANCELLED}, or {@link
     * #INTERRUPTED}).
     *
     * @param v the value to set as the result of the computation.
     * @param t the exception to set as the result of the computation.
     * @param finalState the state to transition to.
     */
    private boolean complete(@Nullable V v, @Nullable Throwable t,
        int finalState) {
      boolean doCompletion = compareAndSetState(RUNNING, COMPLETING);
      if (doCompletion) {
        // If this thread successfully transitioned to COMPLETING, set the value
        // and exception and then release to the final state.
        this.value = v;
        // Don't actually construct a CancellationException until necessary.
        this.exception = ((finalState & (CANCELLED | INTERRUPTED)) != 0)
            ? new CancellationException("Future.cancel() was called.") : t;
        releaseShared(finalState);
      } else if (getState() == COMPLETING) {
        // If some other thread is currently completing the future, block until
        // they are done so we can guarantee completion.
        acquireShared(-1);
      }
      return doCompletion;
    }

该方法是唯一会导致锁释放的方法。

1.首先原子操作设置状态从RUNNING到COMPLETING。如果失败说明有其他线程执行该complete方法时修改状态成功。

2.如果成功,设置value。如果状态是CANCELLED或者INTERRUPTED,返回一个CancellationException异常,否则设置exception(如果有的话)。

3.如果失败的话,判断状态是否是COMPLETING,说明有其他线程正在"成功"执行complete方法(racing成功,可以设置value),此时当前线程是通过acquireShared阻塞,直到其他线程设置完value并执行releaseShared释放锁。

4.触发complete方法的操作

set,setException和cancel方法。

5.get方法

有两个get方法,一个是普通get方法,一个是带超时时间的get方法。这两个方法底层调用的都是getValue方法。

/**
         * Implementation of the actual value retrieval.  Will return the value
         * on success, an exception on failure, a cancellation on cancellation, or
         * an illegal state if the synchronizer is in an invalid state.
         */
        V getValue() throws CancellationException, ExecutionException {
            int state = getState();
            switch (state) {
            case COMPLETED:
                if (exception != null) {
                    throw new ExecutionException(exception);
                } else {
                    return value;
                }

            case CANCELLED:
            case INTERRUPTED:
                throw cancellationExceptionWithCause(
                        "Task was cancelled.", exception);

            default:
                throw new IllegalStateException(
                        "Error, synchronizer in invalid state: " + state);
            }
        }
/**
         * Blocks until {@link #complete(Object, Throwable, int)} has been
         * successfully called.  Throws a {@link CancellationException} if the task
         * was cancelled, or a {@link ExecutionException} if the task completed with
         * an error.
         */
        V get() throws CancellationException, ExecutionException,
                InterruptedException {

            // Acquire the shared lock allowing interruption.
            acquireSharedInterruptibly(-1);
            return getValue();
        }
/**
         * Blocks until the task is complete or the timeout expires.  Throws a
         * {@link TimeoutException} if the timer expires, otherwise behaves like
         * {@link #get()}.
         */
        V get(long nanos) throws TimeoutException, CancellationException,
                ExecutionException, InterruptedException {

            // Attempt to acquire the shared lock with a timeout.
            if (!tryAcquireSharedNanos(-1, nanos)) {
                throw new TimeoutException("Timeout waiting for task.");
            }

            return getValue();
        }

带超时时间的get方法和普通get方法的区别根本在于acquireSharedInterruptibly和tryAcquireSharedNanos,这组方法前面说过,就不再这里说了。

getValue方法:

COMPLETED状态,如果没有exception,直接返回value,如果有exception,用ExecutionException包装该exception然后抛出。

CANCELLED和INTERRUPTED状态,抛出CancellationException异常。

其他情况(不应该出现),抛出IllegalStateException异常。

因为ExecutionException异常不是运行时异常,所以需要try catch捕捉。

6.自己对get方法的扩展

1.getImmediately方法

/**
     * Implementation of the actual value retrieval. No matter whether
     * this value has been set, no matter what has happened to this value,
     * we can get content of this value immediately.
     * <p/>
     * Will return the value on success, an exception on failure, a cancellation
     * on cancellation, or an illegal state if the {@link AbstractFuture#sync}
     * is in an invalid state.
     */
    public V getImmediately() throws ExecutionException {
        return sync.getValue();
    }

因为之前的get方法,无论是带超时时间的还是不带超时间的,都会等待,所以这里提供一个立即获取值的get方法,其实就是不调用acquireSharedInterruptibly和tryAcquireSharedNanos,直接调用底层的getValue方法,该方法会抛出ExecutionException异常。

2.getImmediatelyUnchecked方法

/**
     * Unlike {@link #getImmediately}, this method does not throw a checked exception, and thus should
     * only be used in situations where checked exceptions are not thrown by the future.
     */
    public V getImmediatelyUnchecked() {
        try {
            return getImmediately();
        } catch (ExecutionException e) {
            throw new UncheckedExecutionException(e.getCause());
        }
    }

仿照guava cache的getUnchecked这种方法,把ExecutionException异常包装成一个RuntimeException(UncheckedExecutionException),这样外部调用该方法的时候不用try catch了。

3.getWithoutException方法

/**
     * Get the value immediately without throwing any Exception.
     * The difference between this method
     * and {@link #getImmediately()} is this method is
     * insensitive to state, no matter whether state of this future
     * is {@link com.qunar.flight.api.extender.guava.concurrent.AbstractFuture.Sync#COMPLETED},
     * even if it's {@link com.qunar.flight.api.extender.guava.concurrent.AbstractFuture.Sync#RUNNING},
     * we get also get this value which is null without throwing any Exception
     */
    public V getWithoutException() {
        return sync.value;
    }

这个get方法不会抛出异常,直接返回value,该value有可能是null,也有可能是正常值(即使有异常)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值