和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,也有可能是正常值(即使有异常)。