JUC——FutureTask

在使用多线程的场景中,线程A如何想要获取线程B的执行结果,则需要一直等待线程B执行完毕后才能取到结果,而Future则是线程A在提交线程B时,返回一个Future,线程A通过调用Future.get获取线程B的结果,如果此时线程B还未执行完毕,则线程A调用Future.get会阻塞;

1. Future接口

Future是一个接口,其中FutureTask是Future的一种实现;

public interface Future<V> {
	//  取消一个任务,并返回取消结果。参数表示是否中断线程
    boolean cancel(boolean mayInterruptIfRunning);
	// 判断任务是否被取消
    boolean isCancelled();
	//  判断当前任务是否执行完毕,包括正常执行完毕、执行异常或者任务取消。
    boolean isDone();
	//  获取任务执行结果,任务结束之前会阻塞。
    V get() throws InterruptedException, ExecutionException;
	// 在指定时间内尝试获取执行结果。若超时则抛出超时异常
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

2. FutureTask状态

private volatile int state;
// 任务的初始化状态
private static final int NEW          = 0;
// 表示任务已经执行完成,属于中间状态
private static final int COMPLETING   = 1;
// 表示任务正常完成,属于最终状态
private static final int NORMAL       = 2;
// 表示任务异常完成,属于最终状态
private static final int EXCEPTIONAL  = 3;
// 表示任务还没开始执行就被取消了,非中断方式,属于最终状态
private static final int CANCELLED    = 4;
// 表示任务还没开始执行就被取消了,中断方式,属于中间状态
private static final int INTERRUPTING = 5;
// 表示任务还没开始执行就被取消了,中断方式,属于最终状态
private static final int INTERRUPTED  = 6;

// 需要执行的任务
private Callable<V> callable;
// 结果值,或异常信息
private Object outcome; // non-volatile, protected by state reads/writes
// 正在执行的线程
private volatile Thread runner;
// 等待者链表
private volatile WaitNode waiters;

FutureTask状态流转

在这里插入图片描述

3. FutureTask构造器

public FutureTask(Callable<V> callable) {
	if (callable == null)
		throw new NullPointerException();
	this.callable = callable;
	this.state = NEW;       // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {
	// 将runnable转换成Callable,并且传进来的result是啥get的时候结果就是啥
	this.callable = Executors.callable(runnable, result);
	this.state = NEW;       // ensure visibility of callable
}

4. run方法

FutureTask实现自RunnableFuture,而RunnableFuture 继自 Runnable, Future,所以FutureTask一定有一个run方法:

public void run() {
	// 状态必须是新建,将runner设置为当前线程
	if (state != NEW ||
		!UNSAFE.compareAndSwapObject(this, runnerOffset,
									 null, Thread.currentThread()))
		return;
	try {
		Callable<V> c = callable;
		if (c != null && state == NEW) {
			V result;
			boolean ran;
			try {
				// 执行callable方法 
				result = c.call();
				// 成功标识
				ran = true;
			} catch (Throwable ex) {
				// 出现异常设置状态和响应值
				result = null;
				ran = false;
				setException(ex);
			}
			// 成功 
			if (ran)

				set(result);
		}
	} finally {
		// runner must be non-null until state is settled to
		// prevent concurrent calls to run()
		runner = null;
		// state must be re-read after nulling runner to prevent
		// leaked interrupts
		int s = state;
		// 如果状态为 INTERRUPTING 或者 INTERRUPTED 时,表示线程被中断
		if (s >= INTERRUPTING)
			// 如果正在被中断,则当前线程也不要执行了,一直让出资源就可以了
			handlePossibleCancellationInterrupt(s);
	}
}

protected void setException(Throwable t) {
	// 将状态改为COMPLETING
	if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
		// 设置返回值为异常信息
		outcome = t;
		// 设置状态为 EXCEPTIONAL
		UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
		finishCompletion();
	}
}
// 唤醒park线程
// 当线程调用future.get时,如果此时还没有计算结束,会进行park操作;
private void finishCompletion() {
	// assert state > COMPLETING;
	for (WaitNode q; (q = waiters) != null;) {
		if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
			for (;;) {
				Thread t = q.thread;
				if (t != null) {
					q.thread = null;
					LockSupport.unpark(t);
				}
				WaitNode next = q.next;
				if (next == null)
					break;
				q.next = null; // unlink to help gc
				q = next;
			}
			break;
		}
	}

	done();

	callable = null;        // to reduce footprint
}
// 成功时,设置状态和响应值,并唤醒等待线程
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
	outcome = v;
	UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
	finishCompletion();
}

5. cancel方法

// mayInterruptIfRunning true 表示中断
public boolean cancel(boolean mayInterruptIfRunning) {
	// 如果状态!=null 并且将状态改为INTERRUPTING或CANCELLED
	if (!(state == NEW &&
		  UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
			  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
		return false;
	try {    // in case call to interrupt throws exception
		if (mayInterruptIfRunning) {
			try {
				// 将执行callable的线程进行中断;
				Thread t = runner;
				if (t != null)
					t.interrupt();
			} finally { // final state
				UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
			}
		}
	} finally {
		finishCompletion();
	}
	return true;
}

6. cancel方法

public V get() throws InterruptedException, ExecutionException {
	int s = state;
	// 如果还到达终态,则等待
	if (s <= COMPLETING)
		s = awaitDone(false, 0L);
	// 否则获取响应值;
	return report(s);
}
private int awaitDone(boolean timed, long nanos)
	throws InterruptedException {
	final long deadline = timed ? System.nanoTime() + nanos : 0L;
	WaitNode q = null;
	boolean queued = false;
	for (;;) {
		if (Thread.interrupted()) {
			removeWaiter(q);
			throw new InterruptedException();
		}

		int s = state;
		if (s > COMPLETING) {
			if (q != null)
				q.thread = null;
			return s;
		}
		else if (s == COMPLETING) // cannot time out yet
			Thread.yield();
		else if (q == null)
			q = new WaitNode();
		else if (!queued)
			queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
												 q.next = waiters, q);
		else if (timed) {
			nanos = deadline - System.nanoTime();
			if (nanos <= 0L) {
				removeWaiter(q);
				return state;
			}
			LockSupport.parkNanos(this, nanos);
		}
		else
			LockSupport.park(this);
	}
}
// 这里有可能是因为callable被执行完唤醒,也可能是因为异常原因被唤醒;
private V report(int s) throws ExecutionException {
	Object x = outcome;
	if (s == NORMAL)
		// 如果正常,则响应返回值
		return (V)x;
	if (s >= CANCELLED)
		// 执行过程中出现了异常,抛出异常;
		throw new CancellationException();// 否则,就是EXCEPTIONAL状态了
	throw new ExecutionException((Throwable)x);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值