Java. util. concurrent package source code reading 26 Fork/Join framework Join, forkjoin

Source: Internet
Author: User

Java. util. concurrent package source code reading 26 Fork/Join framework Join, forkjoin

Next let's take a look at what happened to the join method called ForkJoinTask:

Public final V join () {// The doJoin method returns the status of the task. There are three status values: // NORMAL, CANCELLED and predictional // join wait process in the doJoin method if (doJoin ()! = NORMAL) // The reportResult method has three processing methods for the task's three states: // NORMAL: directly return the return value of the getRawResult () method // CANCELLED: Throw CancellationException // EXCEPTIONAL: if an exception is thrown during task execution, this exception is thrown; otherwise, getRawResult () return reportResult () is returned; else // getRawResult is an abstract method, return getRawResult ();}

RecursiveAction and RecursiveTask implement the getRawResult method.

RecursiveAction is used when no return value is returned. Therefore, the getRawResult method returns null.

RecursiveTask is used when a returned value exists. Therefore, the returned value is the return value of the compute method of the abstract method.

 

Next we will continue to look at the core method of join:

Private int doJoin () {Thread t; ForkJoinWorkerThread w; int s; boolean completed; // if (t = Thread. currentThread () instanceof ForkJoinWorkerThread) {// The initialization value of the status value is 0, which is always non-negative before the task is completed // so once the status value changes to negative, indicates that the task has been completed. if (s = status) <0) return s; // check the job stack of the current worker thread (because the LIFO method is used, all of them are called stacks here) // check whether the task at the top of the stack is the current task. if yes, remove the task from the stack and execute it. // then return the status of the task after execution if (w = (ForkJoinWorkerThread) t ). unpushTask (this) {try {completed = exec () ;}catch (Throwable rex) {return setExceptionalCompletion (rex) ;}if (completed) return setCompletion (NORMAL );} // if it is not a stack top task, return w. joinTask (this);} else // return externalAwaitDone () when the external thread waits for the task to end ();}

 

The previous article provides several examples to demonstrate how to implement the RecursiveTask subclass. In the compute method, you can see the call of the join method, that is, the call of ForkJoinWorkerThread to join.

Therefore, let's first look at the implementation of the joinTask method of ForkJoinWorkerThread:

Final int joinTask (ForkJoinTask <?> JoinMe) {ForkJoinTask <?> PrevJoin = currentJoin; currentJoin = joinMe; for (int s, retries = MAX_HELP;) {// The current task has been completed, returns the if (s = joinMe. status) <0) {currentJoin = prevJoin; return s;} // when the number of remaining attempts exceeds 0 (MAX_HELP value is 16), continue to try if (retries> 0) {if (queueTop! = QueueBase) {// check the task stack of the current thread. If the task stack is not empty, true is returned if the current task is at the top of the stack. Otherwise, false is returned, directly think that the attempt fails if (! LocalHelpJoinTask (joinMe) retries = 0;} // else if (retries = MAX_HELP >>> 1) {-- retries; // check whether the current task is in the first position of the Job Queue of a worker thread. // If yes, the task is stolen and the task is executed. TryDeqAndExec // return the status value of the task. Therefore, if the value is greater than or equal to 0, the task has not been executed. // The current thread gives control so that other threads can execute the task if (tryDeqAndExec (joinMe)> = 0) Thread. yield ();} else // The helpJoinTask method checks whether the current task has been stolen by a Worker thread. // It is the latest Task stolen by this thread (currentSteal). If yes, // The current thread helps to execute this task. If this process succeeds, true retries = helpJoinTask (joinMe) is returned )? MAX_HELP: retries-1;} else {// The maximum number of allowed attempts has not been successful. Reset to try retries = MAX_HELP again; // a round of attempts failed, enter the process pool and wait for the task pool. tryAwaitJoin (joinMe );}}}

Let's see what happens when the tryAwaitJoin method of the thread pool is called after an attempt fails:

Final void tryAwaitJoin (ForkJoinTask <?> JoinMe) {int s; // clear the interrupt status of the current thread before checking whether the task is finished.
// Because tryAwaitDone calls wait and may interrupt the Thread. interrupted (); // when the task is still being executed, otherwise, if (joinMe. status> = 0) {// blockedCount plus 1. if the current thread is marked as blocked, true is returned. Otherwise, false if (tryPreBlock () is returned ()) {// call the wait method and wait for the job to complete joinMe. tryAwaitDone (0L); // blockedCount minus 1, mark the current thread as active postBlock ();} // when the thread is closed, cancel this task else if (ctl & STOP_BIT )! = 0L) joinMe. cancelIgnoringExceptions ();}}

Finally, return to the origin. Let's look at the tryAwaitDone method of the task:

Final void tryAwaitDone (long millis) {int s; try {// status is 0 and set to 1. If (s = status)> 0 | (s = 0 & UNSAFE. compareAndSwapInt (this, statusOffset, 0, SIGNAL) & status> 0) {synchronized (this) {if (status> 0) wait (millis );}}} catch (InterruptedException ie) {// because the wait is interrupted, the task cannot be properly executed and ended. Therefore, when calling this method, be sure to // check whether the task has been executed}

 

After finishing the join process in the Worker thread, let's see what happens in other thread join waits. Let's look at the externalAwaitDone method:

Private int externalAwaitDone () {int s; if (s = status)> = 0) {boolean interrupted = false; synchronized (this) {// wait cyclically until the task execution ends while (s = status)> = 0) {if (s = 0) UNSAFE. compareAndSwapInt (this, statusOffset, 0, SIGNAL); else {try {wait () ;}catch (InterruptedException ie) {interrupted = true ;}}}} // clear the interrupt status if (interrupted) Thread. currentThread (). interrupt ();} return s ;}

ExternalAwaitDone has a simple logic. It uses a loop method and wait to wait until the task execution ends.

Since the wait method is used to wait, you must call the notify or yyall method after the task is executed. The setCompletion method is found:

    private int setCompletion(int completion) {        for (int s;;) {            if ((s = status) < 0)                return s;            if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {                if (s != 0)                    synchronized (this) { notifyAll(); }                return completion;            }        }    }

 

Here we have simply finished the Fork/Join framework. Due to the limited level, we have omitted a lot of details. Sorry.




Related Article

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.