FutureTask的使用
CompressFutureTask是一个自己定义的继承FutureTask的类,其中mCallbackDispatcher也是一个接口用于分发可以在这里忽略,我们关心的是set方法
在起初的时候我并不知道这个set方法如何使用,查看文档也是一知半解,所以决定分析源码,下来就看下源码。
public class CompressFutureTask extends FutureTask {
private CallbackDispatcher mCallbackDispatcher;//自己定义的分发对象
private CompressFutureTask(Callable callable) {
super(callable);
}
private CompressFutureTask(Runnable runnable, T result) {
super(runnable, result);
}
public CompressFutureTask(Callable callable, CallbackDispatcher dispatcher) {
super(callable);
this.mCallbackDispatcher = dispatcher;
}
@Override
protected void set(T t) {
super.set(t);
MainThreadExecutor.postToMainThread(t, mCallbackDispatcher);
}
@Override
protected void setException(Throwable t) {
super.setException(t);
}
}
其中最核心的是set方法,这个set方法是在什么时候调用呢?
我们先从观察FutureTask来看。
public interface Future {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
//同时实现了Future接口和Runnable接口
public interface RunnableFuture extends Runnable, Future {
void run();
}
public class FutureTask implements RunnableFuture {
我们继续看看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;
public FutureTask(Callable 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
}
我们继续看第二种构造的内部
Executors.callable(runnable, result);
public static Callable callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter(task, result);
}
private static final class RunnableAdapter implements Callable {
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;
}
}
所以FutureTask构造究其根源就是有一个callable和state,其中callable是我们目前研究的核心。
callable的核心就是call方法。FutureTask第二个构造所产生的callable也就是将Runnable 包装了一层,放执行call方法的时候就执行对应Runnable方法。
我们现在看看FutureTask.run()
public void run() {
if (state != NEW || !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable c = callable;//注意这里是构造的时候拥有的
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();//然后调用call方法
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);//然后设置结果,至于result在这些里面没有操作,只是在call方法执行完之后才执行,所以result这个是要自己的call中操作的对象。
}
} finally {
runner = null;
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
所以只要在线程池中添加任务之后当执行任务的时候调用run的时候,就会触发这一操作,先是调用call方法,然后将返回结果给result,最后set到FutureTask方法中,这些操作都是在子线程中执行的。当我们需要刷入主线程中的时候就要用我们的分发自定义的东西,然后把这个结果通过主线程的Handle进行刷入主线程。