FutureTask的逻辑结构(理解&使用的层次)

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进行刷入主线程。

你可能感兴趣的:(FutureTask的逻辑结构(理解&使用的层次))