In-depth analysis of futuretask

Source: Internet
Author: User

Let's take a look at the comments of futuretask.

Futuretask is an asynchronous computing task that can be canceled. futuretask implements the basic method of future. It can query whether the calculation has been completed by inputting the start cancel operation,

The calculation result can be obtained. The results can only be obtained after the computation is complete. The get method will block when the computation is not complete. Once the computation is complete,

The calculation cannot be started again or canceled.

A futuretask can be used to wrap a callable or runnable object. Because furturetask implements the runnable method
Futuretask can be submitted (submit) to an excutor for execution (excution ).


Futuretask has two important attributes: State runner. The reason why futuretask supports the cancel operation is that these two attributes
The State is the enumerated value:
New 0
Completing execution in progress 1
Normal 2
Predictional exception 3
Cancelled cancel 4
Interrupting interrupted 5
Interrunped is interrupted 6
There are four ways to change the state.
New-> completing-> normal process
New-> completing-> exceptional
New-> canceled
New-> interrunping-> interrrunpted is interrupted

We will study the status change of a task, that is, the lifecycle of a task:

We will first call the constructor to create a futuretask:

public FutureTask(Runnable runnable, V result) {        this.callable = Executors.callable(runnable, result);        this.state = NEW;       // ensure visibility of callable }

When we construct a task, the status is set to new, that is, the starting status of all state change paths.

After a task is created, it will be submitted to executes for execution (of course, we can also start the thread to execute the same effect, but it may be delayed to run the task in the thread pool ).

The change in the subsequent task lifecycle mainly depends on whether the run () method is called first or the cancel () method is called, the execution sequence of the two methods determines the four steps of the task lifecycle.

First, we analyze the situation where the run method is called first. In order to have a more detailed understanding of the run () method, I added some comments in the run method.

Public void run () {/*** first, judge the status of the task. If the status of the task is not new, it indicates that the status of the task has changed (it indicates that it has gone through four possible changes) * If the status is new, the thread for executing the current task will be paid to the runner. Here, the cmpandset is used. If the runner is not empty, it indicates that a thread is already running. * The task will also exit, if the status is new and the runner is empty and the current thread is paid to the runner, the task will continue to be executed (the runner state is volatile * type variable is a thread-safe operation that is very lightweight) * The reason for the state change is that cancel or run is called. **/If (State! = New |! Unsafe. compareandswapobject (this, runneroffset, null, thread. currentthread () return; // start to execute the task try {callable <v> C = callable; /*** if the task to be executed is not empty and the status is new, execute ***/If (C! = NULL & State = new) {v result; Boolean ran; try {// execute task result = C. call (); // if no accident occurs, the execution succeeds. Ran = true;} catch (throwable ex) {// exception result = NULL; ran = false; // setexception (Ex);} // if the transformation is successful, set the result if (RAN) (result );}} finally {// runner must be non-null until State is settled to // prevent concurrent callto run () // set the runner to null regardless of whether the execution is successful. // state must be re-read after nulling runner to prevent // leaked interrupts int S = State; if (s >= interrupting) handlepossiblecancellationinterrupt (s );}}
If the task is successfully executed, the Set () method is called. If any exception occurs, the setexception () method is called.

Let's take a look at the set method first:

Protected void set (V v) {/*** if the State is new, set the state to completing ***/If (unsafe. compareandswapint (this, stateoffset, new, completing) {outcome = V; // set the task to normal over the task unsafe. putorderedint (this, stateoffset, normal); // final state finishcompletion ();}}

If the current status is new, set the status to completing and then set it to normal. The status change caused by this execution process is

New-> completing-> normal

The execution step is to first execute run () and the task is completed normally and cancel () is not called during this process ()

The preceding figure shows the status changes after the task is executed normally. We can see exceptions. If an exception occurs, the setexception () method is called:

Protected void setexception (throwable t) {/*** set the state to completing ***/If (unsafe. compareandswapint (this, stateoffset, new, completing) {outcome = T; // set the task to predictional unsafe. putorderedint (this, stateoffset, exceptional); // final state finishcompletion ();}}

If the current status is new, set the status to completing and then set it to predictional. The status change caused by this execution process is

New-> completing-> predictional
The execution step is to first execute run () and the task throws an exception and no cancel () is called during this process ().

The preceding analysis only shows that the run () method is called, but cancel () is not called during the execution of the run () method, we will analyze the time intersection of the two methods later.

Now let's analyze how the cancel () method is called first.

Cancel () Code

/This method has a parameter to determine whether to interrupt running public Boolean cancel (Boolean mayinterruptifrunning) {/*** this is a bit dizzy. The logical relationship is * equivalent to If (State! = New |! Unsafe. compareandswapint (this, stateoffset, new, mayinterruptifrunning? Interrupting: cancelled) * This means to exit the method if the State is not new, in this case, the task pit is completed, canceled, or interrupted. * If the State is new, set the state to the interrupted or canceled status. ***/If (! (State = new & unsafe. compareandswapint (this, stateoffset, new, mayinterruptifrunning? Interrupting: cancelled) return false; try {// In case call to interrupt throws exception // if it can be interrupted, call the system interrupt method and set the status to interrupted if (mayinterruptifrunning) {try {thread t = runner; If (T! = NULL) T. interrupt ();} finally {// final state unsafe. putorderedint (this, stateoffset, interrupted) ;}} finally {finishcompletion () ;}return true ;}

This method is simple:

1. If it is cancel (false), the status change of the task is

New-> = cancelled

2. If it is cancel (true), the status of the task is

New-> interrupting-> interrupted

At this point, we have seen four state changes of the task. However, both methods are executed independently.

We are analyzing the cross-execution of the two methods (run ()-> cancel ()):

1. If the task has been executed and then cancel () is called ():

A: When cancel (false) is called
A: if the task is being executed and callable. Call () is not returned, or the call () is returned, but the State has not changed.
Therefore, the task call cancel (false) will not affect the execution of the task, but will only affect the status of the task.

B: If callable. Call () has been returned and the status has changed to completing or compled, the task execution and task status will not be affected.

B: Call cancel (true)

A: if the task is being executed and callable. Call () does not return, the State will be set to interrupting, call the interrupt request of the execution thread, and set the status to interrupted. If
The callable. Call () method can respond to interruptions, which may affect the execution of the task. If the method does not respond to interruptions, it will not affect the running of the task. Task status

B: If the task has been executed and the call () has been returned, but the State has not changed, it will not affect the execution of the task, but will only affect the status of the task.

2. After cancel () is called ())

First, calling cancel () will change the State regardless of the call method. When the run () method is executed, the execution of the task will be abandoned if the State is not new.




In-depth analysis of futuretask

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.