Java Multithreading---futuretask Source code Analysis __java

Source: Internet
Author: User
Tags throwable volatile

In multithreaded programming, the creation thread can inherit thread directly or implement the Runnable interface. However, there is a flaw in all 2 ways that the execution results cannot be obtained after the task has been completed.
If you need to get execution results, you must do so by sharing variables or by using thread communication, which can be cumbersome to use.

And since Java 1.5, callable and future,futuretask have been provided, and through them you can get the results of a task after the execution of the task, and today we'll see how futuretask is implemented. Futuretask (JDK 1.8)

From the name we can know that Futuretask is an executable task, but also has the characteristics of future, can get the results of the task execution, first we look at how to use the Futuretask, this will simply involve the concept of the thread pool. Futuretask Use

public class Futuretaskdemo {//asynchronous Task static class task implements CALLABLE<INTEGER&G T {@Override public Integer call () throws Exception {System.out.println () Thread.CurrentThread ()
            . GetName ());
        return 100;

        } public static void Main (string[] args) {Task task = new Task ();

        Use futuretask futuretask<integer> futuretask = new futuretask<integer> (Task);
        Create a thread pool Executorservice executor = Executors.newcachedthreadpool ();

        Perform task Executor.execute (futuretask) asynchronously;
        Use Future future<integer> Future = executor.submit (Task);
            try {//block, wait for the asynchronous task to complete, get the return value of the asynchronous task System.out.println ("Futuretask Result:" + futuretask.get ());
        System.out.println ("Future Result:" + future.get ());
        catch (Exception e) {e.printstacktrace (); }
    }
}

In the above we used respectively futuretask and future to get the return value, the surface seems to be different, in fact, the essence is the same, here through submit submitted to the callable task, the return of future is actually futuretask, this can be in Found in the Abstractexecutorservice source code.

Public <T> future<t> Submit (callable<t> Task) {
    if (task = null) throw new NullPointerException ();
    //Packaging Tasks
    runnablefuture<t> ftask = newtaskfor (Task);
    Execute Task
    execute (ftask);
    return ftask;
}
Protected <T> runnablefuture<t> newtaskfor (Runnable Runnable, T value) {return
    new futuretask<t> (runnable, value);
}

This is the detail in the thread pool, and here it goes, back to our futuretask. Inheritance System


By inheriting relationships we know that Futuretask is actually a combination of runnable and future. Data Structure

/** * The run state of this task, initially NEW.  The Run state * transitions-a terminal state is in methods set, * SetException, and Cancel. During completion, take on * transient values of completing (while outcome are being set) or * interrupting (on Ly while interrupting the runner to satisfy A * Cancel (true). Transitions from this intermediate to final * states use cheaper Ordered/lazy writes because values are unique * and CA
 Nnot be further modified.  * Possible State transitions://Task Status transfer * New-> completing-> normal//Normal completion process * New-> completing->
Exceptional//Abnormal process * New-> cancelled//cancelled * NEW-> interrupting->/interrupted * *  private volatile int state; Task status private static final int NEW = 0; 
Initialization state 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; Breaking private static final int interrupted = 6; Interrupt completion/** the underlying callable;
Nulled out after running * *//callable task private callable<v> callable; 
/** the "result" to "return" or exception to throw ()////Task execution Results private Object outcome; /** the thread running the callable;
Cased during run ()///execute thread private volatile thread runner; /** Treiber stack of waiting threads///Call Get () blocks the waiting thread node private volatile waitnode waiters;

It mainly includes task execution status, callable tasks and task execution results, and describes the task status in detail in the documentation comments. Futuretask Important Method

1, get

Public V get () throws Interruptedexception, Executionexception

Gets the result of the calculation and, if the calculation is not completed, blocks the wait until the end of the calculation or the thread is interrupted
2. Get with timeout function

V get (long timeout, timeunit) throwsinterruptedexception, executionexception, timeoutexception;

Gets the result of the calculation and, if the calculation is not completed, waits for the timeout and throws the timeoutexception exception if a timeout occurs.
3, Isdone

Boolean Isdone ();

Returns whether the calculation completes or returns true if the task completes.

4, Awaitdone

int Awaitdone (Boolean timed, Long Nanos) throws Interruptedexception

Timeout waits for the task to complete, and the return value is the state of future.
5. Cancel the task

Public Boolean Cancel (Boolean mayinterruptifrunning)

When a task is in an cancle state, this method causes the task to never be executed, and when the task is in the started state, (true) attempts to stop the task by interrupting the execution of this task thread, Cancle (FALSE) The thread that is performing this task will not be affected (let the task being performed run), and the method will return false when the task is in the completed state.

6. Task execution Complete callback

protected void Done ()

This method is called when the task completes execution and is null in Futuretask, and can be overridden if necessary. Construction Method

1, designated callable task

Public Futuretask (callable<v> callable) {
    if (callable = = null)
        throw new NullPointerException ();
    this.callable = callable;
    This.state = NEW;       Initialization Status
}

2. Specify runnable tasks and return results

/**
 * Creates a {@code futuretask} that would, upon running, execute the
 * given {@code Runnable}, and arrange that {@code Get} 'll return the ' * given result ' on
 successful completion.
 *
 * @param runnable the runnable task * @param result of the result of
 successful completion. If
 * You don ' t need a particular result, consider using
 * constructions of the form:
 * {@code future<?> f = new futuretask<void> (runnable, NULL)}
 *
/Public Futuretask (runnable runnable, V result) {
    this.callable = executors.callable (runnable, result);
    This.state = NEW;       Ensure visibility of callable
}
Run Method

Now that Futuretask implements the Runnable interface, you need to implement its Run method.

public void Run () {//Determine whether the state is NEW, preventing the task from recurring 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 {//Invoke the call method, returning the results result = C.call ();
            ran = true;
                catch (Throwable ex) {result = null;
                ran = false;
            SetException (ex);
        if (RAN)//If execution succeeds, set the task to run results set (result); } finally {//runner must be non-null until the state are settled to//prevent concurrent to run (
        ) runner = null;
        State must is re-read after nulling runner to prevent//leaked interrupts int s = State; if (s >= interruptinG)//If an interruption occurs, wait for the interrupt process to complete handlepossiblecancellationinterrupt (s); }
}

The entire run method is not complex, internal calls the callable call method, and if the task executes successfully, set the run result to set the task to run

protected void Set (V V) {
    //Update task status
    if (Unsafe.compareandswapint (this, Stateoffset, NEW, completing)) {
        // Set task result
        outcome = V;
        Update task Status
        unsafe.putorderedint (this, stateoffset, NORMAL);//FINAL State
        //closing work
        finishcompletion ();
    }
}
callback and wake blocking threads

When the task is still executing, the call get method blocks the wait, Futuretask internally maintains a thread-waiting list, which we focus on when we analyze the Get method.

private void Finishcompletion () {
    //Assert state > completing;
    Futuretask internally maintains a thread blocking waiting list (calling get method blocking wait results) for
    (Waitnode q; (q = waiters)!= null;) {
        if (Unsafe.compareandswapobject (this, waitersoffset, q, NULL)) {for
            (;;) {
                Thread t = q.thread;
                if (t!= null) {
                    q.thread = null;
                    Wake thread
                    locksupport.unpark (t);
                }
                Waitnode next = Q.next;
                if (next = null) break
                    ;
                Q.next = null; Unlink to help GC
                q = Next;
            }
            break;
        }
    }
    Execute the callback method done
    ();

    callable = null;        To reduce footprint
}
Get Method
Public V get () throws Interruptedexception, executionexception {
    int s = State;
    Check the status of the task and wait if
    (S <= completing)
        s = Awaitdone (false, 0L) if the task has not yet been completed;
    Returns the result return    
    (s);
}

The get () method involves the Awaitdone method, assigns the Awaitdone run result to state, and the final method returns the corresponding value according to the state value, and Awaitdone is the core of the whole futuretask operation.

/** * Awaits completion or aborts on interrupt or timeout.  * @param timed True if use timed waits * @param nanos time to wait, if timed * @return state upon completion/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 the current thread is interrupted, remove from the blocking wait queue (not waiting for results) if (thread.interrupted ()) {removewaiter (q);
        Throw interrupt Exception throw new Interruptedexception ();
        int s = State; If the task has already been completed, and the relevant parameters have been set to complete if (S > Completing) {if (q!= null) Q.thread = NULL;
        Resets//returns status return s; //task execution completed, but some parameters have not been set (reference run method) Else if (s = = completing)//cannot time out yet Thread.yiel D (); Give up the CPU and wait for else if (q = = null) Q = new Waitnode ();
      Creating a thread-waiting node  else if (!queued)//If no team has been queued, proceed to the queue queued = Unsafe.compareandswapobject (this, Waitersoffset,
        Q.next = waiters, q);
            else if (timed) {//If there is a timeout, the timeout waits for Nanos = Deadline-system.nanotime ();
                if (Nanos <= 0L) {//timeout, remove wait thread, return status Removewaiter (q);
            return state;
        }//Timeout waiting for Locksupport.parknanos (this, Nanos);
    else Locksupport.park (this); }
}

The

Waitdone is to join the current thread in the wait queue (waitnode thread variable with current thread), and then block itself with Locksupport, wait for a time-out, or be unblocked, return status (may or may not have completed the task execution) , if an interrupt occurs, a break exception is thrown. Cancel cancels task

public Boolean Cancel (Boolean mayinterruptifrunning) {//new The status contains the task not yet executed and the task is executing (executing: The call method is running) if (!) ( state = = new && Unsafe.compareandswapint (this, Stateoffset, new, mayinterruptifrunning? I
    nterrupting:cancelled))) return false; try {//In case call to interrupt throws exception if (mayinterruptifrunning) {//Indicates whether to interrupt a running task TR
                y {Thread t = Runner; if (t!= null) t.interrupt ();
                Interrupt, can not cancel the task in real time, just set the interrupt flag bit, the target thread needs to detect the flag bit to know whether the interrupt has occurred} finally {//FINAL state//update status
            Unsafe.putorderedint (this, stateoffset, interrupted);
    }} finally {//complete finishcompletion ();
return true; }

If state is not new then exit the method, and the task is completed or canceled or interrupted.
If state is new, it is set to be interrupted or canceled (the new state contains the state in which the task is executing) and, if Mayinterruptifrunning is true, to allow interruption of a running task, interrupt ( interrupt, Can not cancel the task in real time, just set the interrupt flag bit, the target thread needs to detect the flag bit to know whether the interrupt has occurred . return Results

Returns different results depending on the status of the task

Private V (int s) throws executionexception {
    Object x = outcome;
    if (s = = normal)///If the task completes normally, return the result
        (V) x;
    if (s >= cancelled)//Throw cancellation task exception
        throw new Cancellationexception ();
    throw new Executionexception ((throwable) x);
}
Summary

Futuretask internally has a callable task reference, the actual task is callable object, Futuretask defined a variety of states, through the state of the settings and judgments can know the implementation of the task.
Futuretask internally maintains a waiting queue (linked list), and when a Futuretask get method is invoked, the request thread is added to the wait queue when a call is made, and when the task executes (normal or abnormal), the thread in the waiting queue is awakened. This waits for the thread to get the result of the task execution.

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.