Talk about high concurrency (41) parsing the asynchronous execution and state control of each component (17) Task Java.util.concurrent

Source: Internet
Author: User
Tags throwable

Talk about high concurrency (39) parsing java.util.concurrent each component (15) Understanding the design of Executorservice interface The Executorservice interface expands the executor interface, Based on the execution of the task, it provides the management of the framework life cycle, the asynchronous execution of tasks, and the execution of batch tasks. The Abstractexecutorservice abstract class implements the Executorservice interface, which provides the default implementation of task asynchronous execution and bulk execution. This article says asynchronous execution and state control of tasks

Note that the way the executor framework performs tasks is basically performed asynchronously, to threads of the thread pool to execute. Based on the asynchronous execution of the task, the Executorservice performs state control of the asynchronous task through the future interface.


The Submit method can return the future object to control the asynchronous execution of the task. The Submit method has three methods of invocation, passing runnable, runnable and result,callable.

Public future<?> Submit (Runnable Task) {        if (task = = null) throw new NullPointerException ();        runnablefuture<void> ftask = newtaskfor (task, null);        Execute (ftask);        return ftask;    }    Public <T> future<t> Submit (Runnable task, T result) {        if (task = = null) throw new NullPointerException ();        runnablefuture<t> ftask = newtaskfor (task, result);        Execute (ftask);        return ftask;    }    Public <T> future<t> Submit (callable<t> Task) {        if (task = null) throw new NullPointerException () ;        runnablefuture<t> ftask = newtaskfor (Task);        Execute (ftask);        return ftask;    }

As can be seen from the implementation of the submit, the Newtaskfor method is used to fit the interface, returning a runnablefuture type

Protected <T> runnablefuture<t> newtaskfor (Runnable Runnable, T value) {        return new futuretask<t> (runnable, value);    }       Protected <T> runnablefuture<t> newtaskfor (callable<t> callable) {        return new futuretask<t > (callable);    }

Take a look at the future interface-related classes that control the tasks performed asynchronously

1. ruuable represents a task that can be performed by thread, its Run method has no return value, and there is no explicit exception

2. Callable represents a task that can be called, and its call method can have a return value that can throw an explicit exception

3. The future interface is the control of tasks performed asynchronously, including canceling tasks, judging task status, obtaining task results, etc.

4. Runnablefuture is an adaptation to the Runnable interface and the future interface, indicating that a runnable can be controlled.

5. Runnableadapter is an adaptation to the runnable and Callalbe, implements the callable interface, and aggregates the Runnable object

6. Futuretask implements the Runnablefuture interface and unifies the incoming callable and runnable parameters through Runnableadapter



Public interface Runnable {public abstract void run (); public interface callable<v> {    V call () throws Exception;} 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;       }   }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;} Public interface runnablefuture<v> extends Runnable, future<v> {    void Run ();

In Executorservice's Submit method, you can see that the task that is ultimately executed is packaged into a runnablefuture type, which is both runnable can be executor executed, and the future, You can control the state of the runnable that is executed asynchronously.

Focus on Runnablefuture Implementation class Futuretask, the state control of the asynchronously executed task is implemented in this class.

Main properties of Futuretask

1. private volatile int state; The state of the volatile type, which holds the status of the current task in the following ways

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;


2. Private callable<v> callable; A callable object that can get the result of the calculation, encapsulating the incoming task

3. Private Object outcome; The result of the task execution, which can be the result of a normal calculation, or an exception to be returned

4. Private volatile Thread runner; The thread that performs the task

5. Private volatile waitnode waiters; Waiting for the line threads

Futuretask to state, runner, waiters, the 3 objects that require atomic manipulation, do not use atomicxxx atomic variables, but instead use unsafe objects to manipulate the memory directly for atomic operations. Please refer to this chat for unsafe objects High concurrency (17) Parsing java.util.concurrent components (i) Understanding Sun.misc.Unsafe class

Unsafe Mechanics    private static final sun.misc.Unsafe unsafe;    Private static final long stateoffset;    Private static final long runneroffset;    Private static final long waitersoffset;    static {        try {            UNSAFE = Sun.misc.Unsafe.getUnsafe ();            class<?> k = Futuretask.class;            Stateoffset = Unsafe.objectfieldoffset                (K.getdeclaredfield ("state"));            Runneroffset = Unsafe.objectfieldoffset                (K.getdeclaredfield ("Runner"));            Waitersoffset = Unsafe.objectfieldoffset                (K.getdeclaredfield ("waiters");        } catch (Exception e) {            throw new Error (e);        }    }

Look at the main methods of Futuretask

The constructor supports callable types and runnable types, and when using parameters of the runnable type, you need to pass in result as the result of the callable calculation. The adaptation from Runnable to callable is performed with Runnableadapter. The initial state of the Futuretask is new

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.C        Allable (runnable, result);       This.state = NEW; Ensure visibility of callable}//executors.callable () public static <T> callable<t> callable (Runnable T        Ask, T result) {if (task = = null) throw new NullPointerException ();    return new runnableadapter<t> (task, result); }

The Run method is called by the executor worker thread because Futuretask is passed as the Runnable object to the executor execute method.

1. Set the current thread to Futuretask runner.

2. Execute the call method of the incoming callable and pass the results to the result object. If the call method produces an exception, it calls the SetException method to pass the exception object to the outcome property and sets the corresponding state of the Futuretask, first set to completing, and then set to exceptional

3. If the call method executes properly, the set () method is called to pass the result to the outcome property, and the corresponding state of the Futuretask is set to completing, then set to normal

4. call the Finishcompletion method to wake up the blocked thread in the Get () method

public void Run () {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 call            s to run () runner = null;            State must is re-read after nulling runner to prevent//leaked interrupts int s = State;    if (s >= interrupting)            Handlepossiblecancellationinterrupt (s); }} protected void SetException (Throwable t) {        if ( Unsafe.compareandswapint (This, Stateoffset, NEW, completing)) {             outcome = t;            Unsafe.putorderedint (this, stateoffset, exceptional); Final state            finishcompletion ();        }   }protected void Set (V V) {         if (Unsafe.compareandswapint (this, Stateoffset, NEW, completing)) {             outcome = v;            Unsafe.putorderedint (This, stateoffset, NORMAL); Final state            fiNishcompletion ();       }   } 

The Cancel method cancels the task that is performed. When state is new, it can be canceled. If the task is interrupted when the task is canceled, the Futuretask state is set to interrupting, then the interrupt () method of the thread executing the task is called to interrupt the task, and the state is set to interrupted. If you cancel the task without interrupting the task, set the Futuretask state to cancelled directly. Finally call the Finishcompletiong method to wake up and delete the thread waiting in the Get method

  Public Boolean Cancel (Boolean mayinterruptifrunning) {if (state! = NEW) return false; if (mayinterruptifrunning) {if (!            Unsafe.compareandswapint (This, Stateoffset, NEW, interrupting)) return false;            Thread T = Runner;            if (t! = null) t.interrupt (); Unsafe.putorderedint (this, stateoffset, interrupted); Final State} else if (!        Unsafe.compareandswapint (This, Stateoffset, NEW, CANCELLED)) return false;        Finishcompletion ();    return true; } private void Finishcompletion () {       //Assert state > completing;         for (Waitnode Q; (q = waiters) = null;) {            if (Unsafe.compareandswapobject (this, Waitersoffset, q, null)) {              & nbsp; for (;;) {                     Thread t = q.thread;                     if (t! = null) {                         Q.thread = null;                          Locksupport.unpark (t);                    }                     Waitnode next = q.next;                     if (next = = null) &NBSP;&NBSP;&NBSP;&Nbsp;                     break;                     q.next = null; Unlink to help gc                     q = next;                }                break;            }       }         done ();        callable = null;        /To reduce footprint   }//hook method protected void Done () {}

The Get () and get (long timeout, timeunit unit) methods try to get the results of the Futuretask run. The former waits until the Futuretask state is greater than completing, which is the end of call execution, and then the report () method returns the result. The latter waits for timeout time, if timeout throws timeoutexception, otherwise the report () method returns the result

Public V get () throws Interruptedexception, executionexception {        int s = State;        if (s <= completing)            s = Awaitdone (false, 0L);        Return report (s);    }    /**     * @throws cancellationexception {@inheritDoc}     *    /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 Time Outexception ();        Return report (s);    }

The Awaitdone method uses the Locksupport object to implement conditional queue operations, and the Locksupport.park () Locksupport.unpark () method is equivalent to Object.wait (), object.notify () 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 (;;)                {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); }    }

The report method handles the return value of the futuretask and, if executed normally, returns a normal result, throws cancellationexception if it is canceled or interrupted, and if an exception occurs during execution, Just use Executionexception to encapsulate the thrown exception and throw the Executionexception

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

The producer thread that submits the task and the consumer worker thread that performs the task share the Futuretask object, which can interact between the two threads through the state of Futuretask




Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Talk about high concurrency (41) parsing the asynchronous execution and state control of each component (17) Task Java.util.concurrent

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.