Source FutureTask

Introduction

  • FutureTask is an asynchronous task (or asynchronous computation) , For chestnuts, the main thread of logic requires the use of a value, but the value will be responsible for operations come, then the main thread can set up in advance an asynchronous task to calculate this value (calculated in the other thread), and then do other things, and then to get this value by just created asynchronous tasks required when the value of a bit parallel meaning, which can shorten the execution time of the entire logic of the main thread.
  • And 1.6 versions, 1.7 FutureTask no longer based AQS to build, instead of using a simple Treiber Stack internally to save waiting threads.

interface

public interface Future<V> {

//取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束
    boolean cancel(boolean mayInterruptIfRunning);

//任务是否已经取消,任务正常完成前将其取消,则返回 true
    boolean isCancelled();

//任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true
    boolean isDone();

//等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationException
    V get() throws InterruptedException, ExecutionException;

//同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计算超时,将抛出TimeoutException
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

 Source code analysis

working process

FutureTask common ways:

1. Create a task, the actual use, typically in conjunction with the thread pool (ThreadPoolExecutor) use, it is created within FutureTask thread pool.

2. The mission, run method will be called by the general FutureTask worker thread (the current thread for us for the other thread), complete execution.

3. To get results, we generally have the current thread to call the get method to get the results, while getting the task has not been finished, the current thread will be blocked until the task is completed to perform, and then get the results.

4. cancel the task, in some cases abandon mission, the task is canceled.

Internal structure

       
public class FutureTask<V> implements RunnableFuture<V> {
    /** 
     * 内部状态可能得迁转过程: 
     * NEW -> COMPLETING -> NORMAL //正常完成 
     * NEW -> COMPLETING -> EXCEPTIONAL //发生异常 
     * NEW -> CANCELLED //取消 
     * NEW -> INTERRUPTING -> INTERRUPTED //中断 
     */  
    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;

     /** 内部的callable,运行完成后设置为null */  
    private Callable<V> callable;
    /** 如果正常完成,就是执行结果,通过get方法获取;如果发生异常,就是具体的异常对象,通过get方法抛出。 */  
    private Object outcome; // 本身没有volatile修饰, 依赖state的读写来保证可见性。  
    /** 执行内部callable的线程。 */  
    private volatile Thread runner;
    /** 存放等待线程的Treiber Stack*/  
    private volatile WaitNode waiters;
    
    //所谓的Treiber Stack就是由WaitNode组成的(一个单向链表)。
    static final class WaitNode {  
        volatile Thread thread;  //指向block线程
        volatile WaitNode next;  //下一个node
        WaitNode() { thread = Thread.currentThread(); }  
    }  

}    
    

create

    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
    }


    //以下方法为Executors的方法
    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }


It must be written into the state's last , because the state itself is modified by the volatile, so you can guarantee callable visibility. (Because the state will first read before reading the follow-up callable, remember HappenBefore the rules of the volatile write-read it)

status

    /** 
     * 内部状态可能得迁转过程: 
     * NEW -> COMPLETING -> NORMAL //正常完成 
     * NEW -> COMPLETING -> EXCEPTIONAL //发生异常 
     * NEW -> CANCELLED //取消 
     * NEW -> INTERRUPTING -> INTERRUPTED //中断 
     */  

    public boolean isCancelled() {
        return state >= CANCELLED;
    }
    //只要不为NEW就表示结束
    public boolean isDone() {
        return state != NEW;
    }

 

 

    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);
    }

    protected void setException(Throwable t) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = t;
            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
            finishCompletion();
        }
    }

get,set

    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);
    }

    protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

get method will block until the calculation is complete. awaitDone () Method:

   private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            //中断,则移除q,抛出IE
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }
            
            int s = state;
            if (s > COMPLETING) {
                //处理完,返回,如果q!=null,则把线程解绑
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING) // 任务正在执行中,COMPLETING是中间状态。
                Thread.yield();  //释放CPU
            //以下代码:state == NEW,
            else if (q == null)  // q == null,则创建一个WaitNode,绑定Thread
                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);
        }
    }



    private void removeWaiter(WaitNode node) {
        if (node != null) {
            node.thread = null;
            retry:
            for (;;) {          // restart on removeWaiter race
                for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
                    s = q.next;
                    if (q.thread != null)
                        pred = q;
                    else if (pred != null) {
                        pred.next = s;
                        if (pred.thread == null) // check for race
                            continue retry;
                    }
                    else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                          q, s))
                        continue retry;
                }
                break;
            }
        }
    }
 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);
                    }
                    //继续下一个waiter
                    WaitNode next = q.next;
                    if (next == null)
                        break;
                    q.next = null; // unlink to help gc
                    q = next;
                }
                break;
            }
        }

        done();

        callable = null;        // to reduce footprint
    }

get Methods:

1. First, check the current status of the task, if the status indicates that execution is complete, go to Step 2.
2. Get the results, it may get canceled or abnormality, end get the process.
3. If the current task status indicates not executed or being executed, then the current thread into a new node to wait, then enter Treiber Stack were blocked waiting.
4. If a task is finished the worker thread (the current thread is another thread), the worker thread wakes up all the threads waiting on Treiber Stack When finished, so the current thread wakes up, clear the current waiting thread domains on the node, then move on to step 2.
The current thread is blocked waiting for the results in the process may be interrupted, if interrupted, then the node will remove the current thread wait on Treiber Stack corresponding interrupt then throws an exception, the end of the get process.
6. The current thread may also be performed with the blocking timeout wait, if after a timeout, the results have not been implemented, then the node will be in addition to the current thread to wait on the corresponding Treiber Stack, then throw timeout exception, get the process ends .

 

run


    public void run() {
        //不是NEW状态或者设置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 {
                    //执行任务
                    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;
            //处理可能发生的取消中断(cancel(true))。 
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }


    /** 
     * 确保cancel(true)产生的中断发生在run或runAndReset方法过程中。 
     */  
    private void handlePossibleCancellationInterrupt(int s) {  
        // 如果当前正在中断过程中,自旋等待一下,等中断完成。  
        if (s == INTERRUPTING)  
            while (state == INTERRUPTING)  
                Thread.yield(); // wait out pending interrupt  
        // 这里的state状态一定是INTERRUPTED;  
        // 这里不能清除中断标记,因为没办法区分来自cancel(true)的中断。  
        // Thread.interrupted();  
    }  


    protected boolean runAndReset() {  
        if (state != NEW ||  
            !UNSAFE.compareAndSwapObject(this, runnerOffset,  
                                         null, Thread.currentThread()))  
            return false;  
        boolean ran = false;  
        int s = state;  
        try {  
            Callable<V> c = callable;  
            if (c != null && s == NEW) {  
                try {  
                    c.call(); // don't set result  
                    ran = true;  
                } catch (Throwable ex) {  
                    setException(ex);  
                }  
            }  
        } 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  
            s = state;  
            if (s >= INTERRUPTING)  
                handlePossibleCancellationInterrupt(s);  
        }  
        return ran && s == NEW;  
    }  

Visible difference runAndReset and run method just is not set after the implementation of the results, and returns a value indicating whether or not successful.

cancel

//JDK 1.7    
public boolean cancel(boolean mayInterruptIfRunning) {  
        if (state != NEW)  
            return false; //如果任务已经执行完毕,返回false。  
        if (mayInterruptIfRunning) {  
            //如果有中断任务的标志,尝试将任务状态设置为INTERRUPTING  
            if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))  
                return false;  
            //上面设置成功的话,这里进行线程中断。  
            Thread t = runner;  
            if (t != null)  
                t.interrupt();  
            //最后将任务状态设置为INTERRUPTED,注意这里又是LazySet。  
            UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state  
        }  
        //如果没有中断任务的标志,尝试将任务状态设置为CANCELLED。  
        else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))  
            return false;  
        //最后唤醒Treiber Stack中所有等待线程。  
        finishCompletion();  
        return true;  
    }  

//JDK 1.8
    public boolean cancel(boolean mayInterruptIfRunning) {
        if (!(state == NEW &&
              UNSAFE.compareAndSwapInt(this, stateOffset, 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
                    UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
                }
            }
        } finally {
            finishCompletion();
        }
        return true;
    }

In setting mayInterruptIfRunning to true, the internal first by an atomic operation state transitions from NEW to Interrupting and interrupt threads to perform tasks, then the state transitions to INTERRUPTED from Interrupting by operation of a LazySet is , since the latter operation other threads will not be visible immediately, so handlePossibleCancellationInterrupt will have a wait state from INTERRUPTING process becomes INTERRUPTED spin.

 

 

Guess you like

Origin blog.csdn.net/demon7552003/article/details/91625119