Read Doug Lea's article:a Java fork/join Framework section on Work-stealing, which outlines the main points of the algorithm (basically the original translation):
1. Each worker thread maintains a task queue, that is, the task queue in Forkjoinworkerthread.
2. The task queue is a two-way queue, which enables both LIFO and FIFO.
3. Subtasks are added to the task queue of the worker thread where the original task is located.
4. The worker thread takes the task out of the LIFO method, and the task of the backward queue is fetched first (the subtasks are always queued, but need to be executed first).
5. The worker thread's task queue is empty, and a task execution (the so-called stealing task: Steal Work,fifo) is randomly removed from the other thread's task queue.
6. If a worker thread encounters a join operation while another task is being processed, it will wait until the task ends. Otherwise, return directly.
7. If a worker thread steals a task, it will rest for a while with yield or sleep, and then try to steal the task (if all the threads are idle, i.e. no task is running, then the thread will go into a blocking state waiting for the new task to arrive).
Then back to Forkjoinpool's scan method
Private BooleanScan (Forkjoinworkerthread W,inta) {//Scanguard is a 32-bit integer that is used for the index of the worker thread array//The 16th bit is called sg_unit, and 1 means lock//0 to 15 bits is mask intg =Scanguard; //parallelism represents the number of concurrent threads, which generally refers to how many CPUs can run concurrently//The default value is the Availableprocessors method return value of the runtime class, which indicates//Number of processors//A is the number of active worker threads, parallelism is greater than 0, so//condition parallelism = = 1-a satisfies means parallelism is 1 and a is 0.//and add Blockedcount to 0 (meaning no threads because join is blocked),//Two conditions also means that no thread is running, so//means that no task exists on the worker thread, so m=0 is unable to steal the mission.//Smask=0xffff,g & Smask Returns the value Scanguard 0 to 15 digits intm = (parallelism = = 1-a && Blockedcount = = 0)? 0:g &Smask; forkjoinworkerthread[] WS=workers; if(WS = =NULL|| Ws.length <=m)return false; // for(intR = w.seed, K = r, j =-(M + m); J <= m + m; ++j) {Forkjointask<?> T; Forkjointask<?>[] Q;intB, I; //randomly fetching a worker thread from the thread queueForkjoinworkerthread v = ws[k &m]; //determine if a worker thread exists and the task queue for that thread has a task if(V! =NULL&& (b = v.queuebase)! = V.queuetop &&(q= v.queue)! =NULL&& (i = (q.length-1) & B) >= 0) { //steal a task from the queue LongU = (i << ashift) +Abase; if((t = q[i])! =NULL&& V.queuebase = = B &&Unsafe.compareandswapobject (q, U, T,NULL)) { intD = (V.queuebase = b + 1)-V.queuetop; V.stealhint=W.poolindex; //d is the length of the task queue after stealing a task if(d! = 0) signalwork (); W.exectask (t); } R^= R << 13; R ^= R >>> 17; W.seed = r ^ (r << 5); //false indicates scan to task return false; } Else if(J < 0) {//xor shift, update KR ^= R << 13; R ^= R >>> 17; K = R ^= R << 5; } Else++K; } //If the task is not scanned, but the Scanguard is updated to indicate a change in the task if(Scanguard! =g)return false; Else { //remove a task from the thread pool's task queue to executeForkjointask<?> T; Forkjointask<?>[] Q;intB, I; if((b = queuebase)! = Queuetop &&(q= submissionqueue)! =NULL&&(i= (q.length-1) & B) >= 0) { LongU = (i << ashift) +Abase; if((t = q[i])! =NULL&& Queuebase = = B &&Unsafe.compareandswapobject (q, U, T,NULL) ) {Queuebase= B + 1; W.exectask (t); } return false; } return true; } }
The scan method works by stealing a task from another thread's task queue.
"Java.util.concurrent package source reading" Fork/join framework of Work-stealing