我们知道,子线程操作,一般使用的辅助类为 Runnable ,还有一个是 Callable,我们平时使用 Runnable 的比较多,但这两个有什么区别呢?我们先看看源码
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
public interface Runnable {
public abstract void run();
}
很明显,一个有返回值,一个没有返回值。使用 Runnable ,在子线程耗时操作后,获得的值,一般用成员变量保存,或者通过观察者模式,或者Android中的Message 及 Handler来发送和接收数据;Callable 则 本身直接就可以返回这个数据,两个使用原理一样,仅仅是一个封装好了返回值,一个需要自己再去倒腾这个值。
我们知道FutureTask存在于 AsyncTask 中,AsyncTask 是一个异步类,我们发现, 里面有一行执行的代码, exec.execute(mFuture); exec是线程池,那么可以直接执行,继续看:FutureTask<V> implements RunnableFuture<V> ,看看 RunnableFuture 是什么,RunnableFuture<V> extends Runnable, Future<V>, 说明 FutureTask 是一个Runnable, Future中定
义了几个回调方法,下面会分析到。 看到这,会发现,怎么没 Callable ,不要急, mFuture 在创建的时候,会传进去一个WorkerRunnable, 而WorkerRunnable则是实现了一个接口,WorkerRunnable<Params, Result> implements Callable<Result> ,那么就是说,FutureTask 在创建时,就把 Callable 当做参数,传进构造方法了,我们看看 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) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
好,到了这一步,才开始了 FutureTask 的分析。 构造方法中都有 Callable ,两个参数的构造方法中,FutureTask(Runnable runnable, V result), result 则是一个真正的值,继续点进去, this.callable = Executors.callable(runnable, result);
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
private static final class RunnableAdapter<T> implements Callable<T> {
private final Runnable task;
private final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
我们发现,从代码中,可以看出这个一个设计模式,RunnableAdapter 本身也实现了 Callable 接口,把真正的 Runnable task 又包装了一层,task.run(); 执行的是子线程中耗时操作,然而不管得到的是什么,一旦外部调用了Callable的call()方法,返回的值则是传进来的 result。继续看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 的状态,我们知道,FutureTask 是个 Runnable,一旦线程池或者子线程执行,优先执行 run()方法,那么,看看它的源码
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
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;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
这个方法中,看方法中的第一行,
if (state != NEW ||!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
我们知道, state 刚开始值为0,如果不等于0,说明已经被重新赋值了;后面的代码,很熟悉吧!我们看看 U 这个属性,
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long STATE;
private static final long RUNNER;
private static final long WAITERS;
static {
try {
STATE = U.objectFieldOffset
(FutureTask.class.getDeclaredField("state"));
RUNNER = U.objectFieldOffset
(FutureTask.class.getDeclaredField("runner"));
WAITERS = U.objectFieldOffset
(FutureTask.class.getDeclaredField("waiters"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
Class<?> ensureLoaded = LockSupport.class;
}
这是一个静态模版块,会优先执行。看过上一篇文章的童靴都会知道, U 的含义,它通过反射方法,找到成员变量 state 、 runner、 waiters 的地址值,然后通过原子操作,防止多线程并发带来的问题。
成员变量 state 和 runner 好理解,waiters 是一个内部类, 看看源码
static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
}
这是一个数据结构,单链表结构,内部有个成员变量,存储的是线程 Thread 。
继续看run()的源码,U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread())),成员变量 runner 的值为null,把当前所在线程,赋值给 runner, 如果成功,则返回 true;如果 runner 不为null, 或者赋值失败,返回false,则说明已经赋过值了,不用重复操作。
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
意思是,如果状态不为原始状态,或者当前线程已经赋值成功,则不用重复执行该逻辑。
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
}
继续看,非空判断和状态判断,然后就是 result = c.call(); 操作,看看上面的介绍和本身里面做耗时操作,返回值就是这么来的,比如网络请求后,拿到服务器返回的值,在此赋值给result, boolean ran; 是判断 Callable 中执行耗时操作是否有异常,是否成功的标识,如果异常了, result 会置空,ran = false; 然后执行 setException(ex);操作,看看代码
protected void setException(Throwable t) {
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = t;
U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
finishCompletion();
}
}
第一行是把成员变量 state 的值由 0 变为 1,然后把异常赋值给outcome,赋值成功后,把 state 的值,由 1 变为 3,然后执行finishCompletion()方法,此方法是一个循环执行,上述说了个属性waiters,是一个单链表结构,循环执行。如果 result = c.call(); 代码中没有异常,正常执行,则在此逻辑执行后,会继续执行 if (ran){set(result)}; 代码,此刻
protected void set(V v) {
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = v;
U.putOrderedInt(this, STATE, NORMAL); // final state
finishCompletion();
}
}
把 state 的值由 0 变为 1,然后把获取到的值 result 赋值给 outcome, 然后再把 state 的值由 1 变为 2,执行 finishCompletion() 方法,同上。主要的逻辑就上面这一点,其他的都是一些对外暴露的方法和细节逻辑,比如对外提供值,是否取消此操作成功等。
比如对外暴露值的 get() 方法,
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
如果还没获取到值,耗时操作没执行完,会进入等待时刻,然后等到获取到值,进行下一步,
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null)
throw new NullPointerException();
int s = state;
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
return report(s);
}
此方法比着上面,多了一个时间限制,如果超过时间 限制,直接报异常;时间内得到值,把state进行赋值,并返回给 s ,进行下一步 report(s)
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
如果执行完毕,则返回 outcome 值 ,如果在此过程中被执行 cancle 取消操作,那么就抛异常。
public boolean isCancelled() {
return state >= CANCELLED;
}
public boolean isDone() {
return state != NEW;
}
这两个方法,上面是根据 state 值判断是否取消成功, 下面是否开始执行。都是根据状态值判断,再看看 cancel(boolean mayInterruptIfRunning) 方法,参数的意思是如果执行了,是否允许中断;
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW &&
U.compareAndSwapInt(this, STATE, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
U.putOrderedInt(this, STATE, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
老样子,第一行代码,也是一个校验,如果 state 值为 0, 根据 mayInterruptIfRunning是否为true 把 state 值由 0 变为 5 或者 4,如果都成功了,则继续执行下一步,否则,终止。返回失败,比如已经开始执行完了耗时操作,state 值已经变成了1 ,此时就不能取消了,直接返回false,表示失败;如果还没开始执行,或者执行了,但还没执行完,还在耗时操作之中,则根据 mayInterruptIfRunning 值,state 值由 0 变为 5 或者 4,此时,即使执行了run()方法,set(v)时也会有 if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING))这个校验,此时 state 为5 或者 4 ,就不会继续赋值了。 继续往下看, 如果 mayInterruptIfRunning 为true,则会获取到耗时操作的线程,如果该线程已经执行,说明线程存在,不为空,则把它强制终止,然后 会把 state 值由 5 变为 6,表示已经终止,5的意思是终止进行中。然后会执行 finishCompletion(); 方法,上面分析过了。
awaitDone()方法和 removeWaiter(WaitNode node) 方法,主要就是需要了解链表数据结构,里面就是执行循环,和 state 状态赋值比较,做一下操作。