1. summary

We are studying the topic of system storage , summary , I feel a little tired in the process of finishing and writing , Plus the second proofreading of the manuscript recently , The learning and writing progress of the system storage project is obviously lagging behind , In particular, it was written Ceph
MON Knowledge points . So follow up 1,2 I plan to change the direction of study and arrangement in the next month , After that, I will continue to write the topic of system storage . What direction should we take ? Um. ~~ There is still a part of the previous thread column that hasn't been filled in , Just go ahead and fill in the hole .

java.util.concurrent.ForkJoinPool from Java master Doug
Lea Presided over the compilation , It can split a large task into multiple subtasks for parallel processing , Finally, the sub task results are merged into the final calculation results , And output . In this paper, the Fork/Join Explanation of the framework , be based on JDK1.8+ Medium Fork/Join Framework implementation , Reference Fork/Join The main source code of the framework is also based on JDK1.8+.

These articles will attempt to explain Fork/Join Knowledge points of framework , In order to treat myself , This paper gives some inspirations to readers in the design of concurrent programs . The article will first explain Fork/Join Basic use of framework , As well as the use of which need to pay attention to the key points ; Then use Fork/Join The framework solves some practical problems ; Finally, I'll explain Fork/Join How the framework works .

2. Fork/Join Basic use of framework

Here's a simple one Fork/Join Examples of using frameworks , In this example, we calculate 1-1001 Accumulated value :
/** * This is a simple one Join/Fork Calculation process , take 1—1001 Adding numbers */ public class TestForkJoinPool {
private static final Integer MAX = 200; static class MyForkJoinTask extends
RecursiveTask<Integer> {// The value at which the subtask begins to calculate private Integer startValue; // The value of the subtask end calculation
private Integer endValue; public MyForkJoinTask(Integer startValue , Integer
endValue) {this.startValue = startValue; this.endValue = endValue; } @Override
protected Integer compute() { // If conditions hold , This indicates that the number of values to be calculated for this task is small enough // It's time to add up if
(endValue - startValue < MAX) { System.out.println(" The part that starts the calculation :startValue = " +
startValue +";endValue = " + endValue); Integer totalValue = 0; for(int index =
this.startValue ; index <= this.endValue ; index++) { totalValue += index; }
return totalValue; } // Otherwise, split the task , Split into two tasks else { MyForkJoinTask subTask1 = new
MyForkJoinTask(startValue, (startValue + endValue) /2); subTask1.fork();
MyForkJoinTask subTask2 =new MyForkJoinTask((startValue + endValue) / 2 + 1 ,
endValue); subTask2.fork();return subTask1.join() + subTask2.join(); } } }
public static void main(String[] args) { // This is Fork/Join Thread pool of framework ForkJoinPool pool
=new ForkJoinPool(); ForkJoinTask<Integer> taskFuture = pool.submit(new
MyForkJoinTask(1,1001)); try { Integer result = taskFuture.get();
System.out.println("result = " + result); } catch (InterruptedException |
ExecutionException e) { e.printStackTrace(System.out); } } }
The code is simple , There are relevant notes at key locations . Here, the key points in the above examples are explained . Let's take a look at the possible execution results of the above example code :
The part that starts the calculation :startValue = 1;endValue = 126 The part that starts the calculation :startValue = 127;endValue = 251
The part that starts the calculation :startValue = 252;endValue = 376 The part that starts the calculation :startValue = 377;endValue = 501
The part that starts the calculation :startValue = 502;endValue = 626 The part that starts the calculation :startValue = 627;endValue = 751
The part that starts the calculation :startValue = 752;endValue = 876 The part that starts the calculation :startValue = 877;endValue = 1001
result =501501
2-1. Work sequence diagram

The following figure shows the working process of the above code , But in fact Fork/Join The internal working process of the framework is much more complicated than this diagram , For example, how to decide on one recursive
task Which thread is used to run ; Another example is how to decide to be a task / Subtask submitted to Fork/Join Behind the frame , Do you want to create a new thread to run or to queue it .

So if you don't understand it in depth Fork/Join Operation principle of the framework , Just observe the operation effect according to the simplest use example above , So we can only know that the subtask is in Fork/Join After the frame is split small enough , And the internal use of multithreading to complete the calculation of these small tasks, and then merge the results upward , Finally, the top-level results are formed . No hurry , Step by step , Let's start with the outline process diagram .

Top level task usage in the diagram submit Method is submitted to Fork/Join In the frame , The latter puts the former into a thread to run , In the task compute Method to start the task T1 Analysis . If the number range that the current task needs to accumulate is too large ( The code is set to be greater than 200), The calculation task is divided into two subtasks (T1.1 and T1.2), Each subtask is responsible for calculating half of the data accumulation , See in the code fork method . If the number range to be accumulated in the current subtask is small enough ( Less than or equal to 200), It accumulates and returns to the upper level task .

2-2. ForkJoinPool Constructor

ForkJoinPool There are four constructors , The constructor with the most complete parameters is shown below :
public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,boolean asyncMode)

parallelism: Parallelizable level ,Fork/Join The framework will be based on this level of parallelism , Determines the number of threads executed in parallel within the framework . Each parallel task has a thread to process , But do not interpret this property as Fork/Join The maximum number of threads in the framework , Do not combine this property with ThreadPoolExecutor In thread pool corePoolSize,maximumPoolSize Property , because ForkJoinPool The organizational structure and working style of the company are totally different from those of the latter . And in subsequent discussions , Readers can also find that Fork/Join The relationship between the number of threads that can exist in the framework and the value of this parameter is not absolute ( There is a basis, but it is not entirely up to it ).


factory: When Fork/Join When the framework creates a new thread , Threads are also used to create factories . It's just that the thread factory no longer needs to be implemented ThreadFactory Interface , It needs to be realized ForkJoinWorkerThreadFactory Interface . The latter is a functional interface , You just need to implement a newThread Methods . stay Fork/Join There is a default in the framework ForkJoinWorkerThreadFactory Interface implementation :DefaultForkJoinWorkerThreadFactory.

handler: Exception capture processor . When an exception occurs in the executed task , And is thrown from the task , Will be handler capture .


asyncMode: This parameter is also very important , It literally means asynchronous mode , It doesn't mean Fork/Join Does the framework work in synchronous mode or asynchronous mode .Fork/Join In the framework, a queue of tasks to be executed is prepared for each independent working thread , This task queue is a bi-directional queue composed of arrays . In other words, the task to be executed exists in the queue , That is, you can use the first in first out mode , You can also use the last in first out mode .

When asyncMode Set to ture When , The queue works in the first in first out mode ; On the contrary, it works in the way of last in first out , The value defaults to false:
...... asyncMode ? FIFO_QUEUE : LIFO_QUEUE, ......

ForkJoinPool There are two other constructors , A constructor only takes parallelism parameter , Both can be set Fork/Join Maximum number of parallel tasks for the framework ; The other constructor takes no arguments , The maximum number of parallel tasks is also a default —— The current operating system can use CPU Number of cores (Runtime.getRuntime().availableProcessors()). actually ForkJoinPool There is also a private one , Native constructor , The three constructors mentioned above are private to this , Call of native constructor .
...... private ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory
factory, UncaughtExceptionHandler handler,int mode, String workerNamePrefix) {
this.workerNamePrefix = workerNamePrefix; this.factory = factory; this.ueh =
handler;this.config = (parallelism & SMASK) | mode; long np = (long
)(-parallelism);// offset ctl counts this.ctl = ((np << AC_SHIFT) & AC_MASK) |
((np << TC_SHIFT) & TC_MASK); } ......

If you're right Fork/Join The framework has no specific implementation requirements , You can use a constructor without any parameters directly . In other words, it is recommended to use the CPU Number of cores as Fork/Join Maximum number of parallel tasks in the framework , This ensures that CPU When processing parallel tasks , Running state switching between task threads should be minimized ( Actually single CPU State switching between threads on the kernel is basically unavoidable , Because the operating system runs multiple threads and processes at the same time ).

2-3. fork Methods and join method

Fork/Join Provided in the framework fork Methods and join method , It can be said that they are the two most important methods provided in the framework , They and parallelism“ Number of parallel tasks ” Cooperation , Subtasks that can cause splitting T1.1,T1.2 even to the extent that TX stay Fork/Join Different operation effects in the framework . for example TX Subtask or wait for another existing thread to run the associated subtask , Or running TX In the thread of “ recursion ” Perform other tasks , Or start a new thread to run the subtask ……

fork Method is used to put the newly created subtask into the work
queue In line ,Fork/Join The framework will execute concurrently according to the current execution ForkJoinTask Mission oriented ForkJoinWorkerThread Thread status , The decision is to have the task wait in the queue , Or create a new one ForkJoinWorkerThread Thread runs it , Or evoke others who are waiting ForkJoinWorkerThread Thread runs it .

There are several element concepts that need attention ,ForkJoinTask The task is to be able to Fork/Join Specific tasks running in the framework , Only this type of task can be used in Fork/Join Split run and merge run in framework .ForkJoinWorkerThread Thread is a kind of Fork/Join Feature threads running in the framework , In addition to the features of ordinary threads , The main characteristics are
every last ForkJoinWorkerThread Each thread has an independent task waiting queue (work queue), This task queue is used to store several subtasks that are split in this thread .

join Method is used to block the current thread , Until the corresponding subtask has finished running and returns the execution result . perhaps , If this subtask exists in the task waiting queue of the current thread (work
queue) in , This sub task will be taken out “ recursion ” implement . Its purpose is to get the running result of the current subtask as soon as possible , Then go ahead .

3. use Fork/Join Solving practical problems

( To be continued )

©2019-2020 Toolsou All rights reserved,
QQ Login interface implementation code implementation mysql Addition, deletion, modification and query of database JAVA Experiment 4 set and functional programming experiment about String How to create objects VHDL——4 choose 1 Data selector C language ( Guess numbers games ) Blue Bridge Cup MCU advanced module --NE555 I don't memorize eight part essays , You go to the interview ? Hill sorting of sorting algorithm ——c++ realization python What does built-in function mean _python What are the built-in functions