FutureTask的get方法實現: 1、允許多個線程get這個結果 2、多個線程get這個結果時,可能任務還沒運行完。 3、任務運行完成後才能拿到結果,而且這個時候要讓get結果的多個線程都可以拿到結果
/**
* FutureTask的get方法實現:
* 1、允許多個線程get這個結果
* 2、多個線程get這個結果時,可能任務還沒運行完。
* 3、任務運行完成後才能拿到結果,而且這個時候要讓get結果的多個線程都可以拿到結果
*/
public class MyFutureTask<V> implements Runnable, Future<V> {
private final Sync sync;
public MyFutureTask(Callable<V> callable) {
if (callable == null) {
throw new NullPointerException();
}
sync = new Sync(callable);
}
private final class Sync extends AbstractQueuedSynchronizer {
/**
* 表示任務正在執行
*/
private static final int RUNNING = 1;
/**
* 表示任務已經運行完畢
*/
private static final int RAN = 2;
/**
* 執行結果
*/
private V result;
private Callable<V> callable;
public Sync(Callable<V> callable) {
super();
this.callable = callable;
}
/*任務沒完成,讓get結果的線程全部進入同步隊列
* acquireShared方法返回了,說明可以拿結果了,直接返回結果*/
V innerGet() throws InterruptedException, ExecutionException {
acquireShared(0);
return result; // 成功執行完成,返回執行結果。
}
/*對任務的狀態進行變化,設置執行結果,並喚醒所有等待結果的線程*/
void innerSet(V v) {
for (; ; ) {
int s = getState(); // 獲取任務執行狀態。
if (s == RAN) {
return; // 如果任務已經執行完畢,退出。
}
// 嘗試將任務狀態設置爲執行完成。
if (compareAndSetState(s, RAN)) {
result = v; // 設置執行結果。
releaseShared(0); // 釋放控制權。
return;
}
}
}
@Override
protected boolean tryReleaseShared(int releases) {
return true;
}
/*任務沒完成,返回-1,讓get結果的線程全部進入同步隊列
* 返回1,可以讓所有在同步隊列上等待的線程一一去拿結果*/
@Override
protected int tryAcquireShared(int acquires) {
return this.getState() == RAN ? 1 : -1;
}
void innerRun() {
if (this.compareAndSetState(0, RUNNING)) {
if (this.getState() == RUNNING) {//再檢查一次,雙重保障
try {
/*將call()方法的執行結果賦值給Sync中的result*/
this.innerSet(this.callable.call());
} catch (Exception e) {
e.printStackTrace();
}
} else {
/*如果不等於RUNNING,表示被取消或者是拋出了異常。這時候喚醒調用get的線程。*/
this.releaseShared(0);
}
}
}
}
@Override
public void run() {
this.sync.innerRun();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
throw new UnsupportedOperationException();
}
@Override
public boolean isCancelled() {
throw new UnsupportedOperationException();
}
@Override
public boolean isDone() {
throw new UnsupportedOperationException();
}
@Override
public V get() throws InterruptedException, ExecutionException {
return this.sync.innerGet();
}
@Override
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException,
TimeoutException {
throw new UnsupportedOperationException();
}
}