Multithreading Fork/join Parallel Computing

Source: Internet
Author: User

1. What is the Fork/join framework

The Fork/join framework is a framework that JAVA7 provides for parallel execution of tasks, a framework that divides large tasks into small tasks, and ultimately summarizes the results of a large task after each small task.

We can understand the fork/join framework by fork and join two words, fork is to divide a big task into several sub-tasks parallel execution, join is to merge the execution result of these subtasks, finally get the result of this big task. For example, calculate 1+2+ ... +10000, can be divided into 10 sub-tasks, each sub-task to sum 1000 numbers, and finally summarize the results of these 10 subtasks. The Fork/join flow chart is as follows:

2. Work-Stealing algorithms

The work-stealing (work-stealing) algorithm refers to the execution of a thread stealing a task from another queue. The operating flow chart for work stealing is as follows:

So why do you need to use a work-stealing algorithm? If we need to do a larger task, we can divide the task into a number of non-dependent sub-tasks, in order to reduce the competition between the threads, and then put these sub-tasks into different queues, and create a separate thread for each queue to perform the tasks in the queue, the thread and queue one by one corresponding, For example, a thread is responsible for handling tasks in the a queue. However, some threads will finish the task in their own queue, while other threads have tasks waiting to be processed in the queue. Instead of waiting for a live thread to work with other threads, it goes to another thread's queue to steal a task to execute. At this point they will be accessing the same queue, so in order to reduce the competition between the stealing task thread and the stolen task thread, a double-ended queue is usually used, the stolen task thread will always execute from the head of the double-ended queue, and the thread that steals the task will always carry the task from the tail of the double-ended queue.

The advantage of a work-stealing algorithm is that it takes full advantage of threads for parallel computing and reduces the competition between threads, with the disadvantage of being competitive in some cases, such as when there is only one task in a double-ended queue. and consumes more system resources, such as creating multiple threads and multiple double-ended queues.

3. Introduction to the Fork/join framework

We are already well aware of the requirements of the Fork/join framework, so we can think about how to design a fork/join framework if we want to design it. This thinking helps you understand the design of the Fork/join framework.

The first step is to split the task. First we need to have a fork class to divide the large task into sub-tasks, it is possible that the subtasks are still very large, so it is necessary to continue to split, until the split sub-task is small enough.

The second step executes the task and merges the results. split subtasks are placed in a double-ended queue , and several boot threads get task execution from the double-ended queue, respectively. The results of the subtasks are uniformly placed in a queue, starting a thread to take the data from the queue, and then merging the data.

Fork/join uses two classes to accomplish both of these things:

    • Forkjointask: To use the Forkjoin framework, you must first create a forkjoin task. It provides a mechanism for executing the Fork () and join () operations in a task, and typically we do not need to inherit the Forkjointask class directly, but only inherit its subclasses, the Fork/join framework provides the following two subclasses:
      • Recursiveaction: Used for tasks that do not return results.
      • Recursivetask: Used for tasks that have return results.
    • The forkjoinpool:forkjointask needs to be executed through Forkjoinpool, and the subtasks are added to the double-ended queue maintained by the current worker thread, to the head of the queue. when there is no task in the queue for a worker thread, it randomly fetches the end of the queue from the other worker threads for any Services .
4. code example:
 PackageHeapStark.blogCode.concurrent.forkJoin;ImportJava.util.concurrent.RecursiveTask;/*** Created by Wangzhilei3 on 2017/12/19.*/ Public classSumtaskextendsRecursivetask<integer> {    Private intstart; Private intend;  PublicSumtask (intStartintend) {         This. Start =start;  This. end =end; } @OverrideprotectedInteger Compute () {System.out.println (Thread.CurrentThread (). GetName ()); if(start==end) {            returnstart; }Else if(end-start==1){            returnEnd+start; }Else{Sumtask Left=NewSumtask (Start, (start+end)/2); Sumtask Right=NewSumtask ((start+end)/2+1, end);            Left.fork ();            Right.fork (); returnLeft.join () +Right.join (); }    }}    /*** Fork Join Test*/@Test Public voidforkjointest () {Forkjoinpool pool=NewForkjoinpool (); Sumtask Sumtask=NewSumtask (1, 10); Future<Integer> future =Pool.submit (Sumtask); Try {            assert(Future.get () = = 55); } Catch(Interruptedexception |executionexception e)        {E.printstacktrace (); }    }
5. Exception Handling:

Forkjointask may throw an exception while executing, but we cannot catch the exception directly on the mainline thread, so Forkjointask provides the iscompletedabnormally () method to check if the task has been thrown or has been canceled. And the exception can be obtained by Forkjointask's GetException method. Use the following code:

        if (sumtask.iscompletedabnormally ()) {            System.out.println (); Sumtask.getexception ();        }
6. The implementation principle of the Fork/join framework

Recursivetask Inheritance Relationship:

Recursivetask is a forkjointask, and the top level realizes the future.

forkjoinworkerthread for the corresponding worker thread, Forkjoinworkerthread holds a corresponding Forkjoinpool, and a corresponding workqueue.

Final Forkjoinpool pool;                The pool this thread works in
Final Forkjoinpool.workqueue WorkQueue; Work-stealing Mechanics

Forkjoinpool is:

Forkjoinpool consists of the Forkjointask array (final Forkjoinpool.workqueue WorkQueue) and the Forkjoinworkerthread array, The Forkjointask array is responsible for storing the tasks that the program submits to Forkjoinpool, and the Forkjoinworkerthread array is responsible for performing those tasks.

Forkjointask's Fork method implementation principle. When we call Forkjointask's Fork method, the program calls Forkjoinworkerthread's Pushtask method to perform the task asynchronously, and then returns the result immediately. The code is as follows:

 
 public  final  forkjointask<v><        Span style= "COLOR: #000000" > fork () {Thread T;  if  ((t = Thread.CurrentThread ())  instanceof   Forkjoinworkerthread)  // ((forkjoinworkerthread) t). Workqueue.push (this  );  else   ForkJoinPool.common.externalPush (        /span>this  );  return  this     ; } 
Final Forkjoinpool.workqueue WorkQueue;
        Final voidPush (forkjointask<?>Task) {Forkjointask<?>[] A;            Forkjoinpool p; intB = base, S =top, N; if((a = array)! =NULL) {//Ignore if queue removed                intm = a.length-1;//fenced write for task visibilityU.putorderedobject (A, ((M & S) << Ashift) +Abase, Task); U.putorderedint ( This, Qtop, S + 1); if((n = s-b) <= 1) {                    if((p = pool)! =NULL) p.signalwork (P.workqueues, This); }                Else if(N >=m) Growarray (); }        }

The Pushtask method stores the current task in the Forkjointask array queue. Then call Forkjoinpool's Signalwork () method to wake up or create a worker thread to perform the task. The code is as follows:

Forkjointask the Join method implementation principle. The primary role of the Join method is to block the current thread and wait for the results to be obtained. Let's take a look at the implementation of the Join method of Forkjointask, with the following code:

     Public Final V Join () {        int  s;         if ((s = Dojoin () & done_mask)! = NORMAL)            reportexception (s)        ; return Getrawresult ();    }

First, it calls the Dojoin () method, using the Dojoin () method to get the status of the current task to determine what results are returned, there are four kinds of task status: Completed (NORMAL), Canceled (CANCELLED), Signal (SIGNAL) and an exception (exceptional).

    • If the task status is completed, the task results are returned directly.
    • If the task status is canceled, the cancellationexception is thrown directly.
    • If the task status throws an exception, the corresponding exception is thrown directly.

Let us then analyze the implementation code for the Dojoin () method:

    private int Dojoin () {        int s; Thread T; Forkjoinworkerthread wt; Forkjoinpool.workqueue W;        Return (s = status) < 0? S:            ((t = Thread.CurrentThread ()) instanceof Forkjoinworkerthread)?            (w = (WT = (forkjoinworkerthread) t). workQueue).            Tryunpush (This) && (s = doexec ()) < 0? S:            Wt.pool.awaitJoin (W, this, 0L):            externalawaitdone ();    }

  

In the Dojoin () method, first by looking at the status of the task, see whether the task has been completed, if done, then directly return to the task status, if not completed, then remove the task from the task array and execute. If the task completes successfully, the task state is set to normal, and if an exception occurs, the exception is logged and the task status is set to exceptional.

Multithreaded Fork/join Parallel computing

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.