-
Notifications
You must be signed in to change notification settings - Fork 1
/
ForkJoinPool.drawio
1094 lines (1094 loc) · 229 KB
/
ForkJoinPool.drawio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<mxfile host="Electron" modified="2024-04-13T08:25:41.672Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.7.5 Chrome/114.0.5735.289 Electron/25.8.1 Safari/537.36" etag="zvu9Mt3IItwB3YCBAej5" version="21.7.5" type="device" pages="2">
<diagram id="CkkpEGL-JcrP4vNnKdJq" name="工作原理">
<mxGraphModel dx="2123" dy="727" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Oymi44IFPG7ip9I0upf_-1" value="<h1 style="font-size: 16px;"><font style="font-size: 16px;">ForkJoinPool 工作原理</font></h1><p style="font-size: 10px;"><font style="font-size: 10px;">源码不是很好理解,有很多反直觉的设计,一个字段可能拆分了好几块表示不同的含义,一些方法有很多循环、条件判断、位运算,堆在一起,很难推测作者的真实用意,需要结合上下文代码进行理解,最好是复制一份代码加上日志和断点进行调试。</font></p><p style="font-size: 10px;"><font style="font-size: 10px;"><b style="">预备知识:</b><br>1)最好先对ThreadPoolExecutor有个清晰的认识,方便理解ForkJoinPool;<br>2)ThreadLocalRandom.getProbe() 探针;参考java-relearn 或 参考网文:<a style="" href="https://aobing.blog.csdn.net/article/details/115450889">https://aobing.blog.csdn.net/article/details/115450889</a><br>3)理解“UNSAFE CAS 自旋”并发同步操作,以及UNSAFE修改对象的方法和Java对象的内存结构,代码里面有大量这种操作;</font></p><p style="font-size: 10px;"><font style="font-size: 10px;">基于测试:<br><span style="background-color: initial;">java-async/async-future/ThreadExhaustionTest.java<br></span><span style="background-color: initial;">java-async/async-future/ArraySumMain.java</span></font></p>" style="text;html=1;strokeColor=none;fillColor=none;spacing=5;spacingTop=-20;whiteSpace=wrap;overflow=hidden;rounded=0;" parent="1" vertex="1">
<mxGeometry x="40" y="20" width="600" height="160" as="geometry" />
</mxCell>
<mxCell id="a_vHJ03TcrBo9rNO5nsq-12" value="<div style="font-size: 9px;">线程池一共下面6种运行状态<br style=""><div style="">int&nbsp; RSLOCK&nbsp; &nbsp; &nbsp;= 1;</div><div style="">int&nbsp; RSIGNAL&nbsp; &nbsp; = 1 &lt;&lt; 1;</div><div style="">int&nbsp; STARTED&nbsp; &nbsp; = 1 &lt;&lt; 2;</div><div style="">int&nbsp; STOP&nbsp; &nbsp; &nbsp; &nbsp;= 1 &lt;&lt; 29;</div><div style="">int&nbsp; TERMINATED = 1 &lt;&lt; 30;</div><div style="">int&nbsp; SHUTDOWN&nbsp; &nbsp;= 1 &lt;&lt; 31; //-2147483648</div></div>" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=10;fontColor=#007FFF;" parent="1" vertex="1">
<mxGeometry x="1190" y="600" width="180" height="80" as="geometry" />
</mxCell>
<mxCell id="X0HKkTIcBq6q-AQzs4eG-13" value="<span style="font-size: 10px;"><b>任务往队列插入元素流程</b>:<br>通过<b>UNSAFE</b>将<b>ForkJoinTask</b>插入数组q.top位置,然后更新q.top的值(+1)<br><br>因为是用的UNSAFE往数组插入的元素,UNSAFE是靠偏移量指针(byte为单位)修改的<br style="">根据JVM中对象内存结构,需要先计算出其<b>偏移位置</b>是<br style="">markword (8) + 压缩类型指针(4) + 数组长度(4) + top * 指针类型(4)<br style="">里面最内部的按位与操作是为了防止索引溢出<br style="font-size: 6px;"></span>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=6;fontColor=#3399FF;" parent="1" vertex="1">
<mxGeometry x="2290" y="501" width="410" height="100" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-2" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ForkJoinPool</b> extends AbstractExecutorService<br style="font-size: 10px;"></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//用于取ctl低16位,bit:0-15</font></p><p style="margin: 0px 0px 0px 4px;">static final int <b>SMASK</b>&nbsp; &nbsp; &nbsp; &nbsp; = 0xffff;&nbsp; &nbsp; &nbsp; &nbsp; // short bits == max index</p><p style="margin: 0px 0px 0px 4px;">static final int MAX_CAP&nbsp; &nbsp; &nbsp; = 0x7fff;&nbsp; &nbsp; &nbsp; &nbsp; // max #workers - 1</p><p style="margin: 0px 0px 0px 4px;">static final int EVENMASK&nbsp; &nbsp; &nbsp;= 0xfffe;&nbsp; &nbsp; &nbsp; &nbsp; // even short bits</p><p style="margin: 0px 0px 0px 4px;">static final int SQMASK&nbsp; &nbsp; &nbsp; &nbsp;= 0x007e;&nbsp; &nbsp; &nbsp; &nbsp; // max 64 (even) slots</p><p style="margin: 0px 0px 0px 4px;">// Masks and units for WorkQueue.scanState and ctl sp subfield</p><p style="margin: 0px 0px 0px 4px;">static final int SCANNING&nbsp; &nbsp; &nbsp;= 1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// false when running tasks</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// 非与工作者线程绑定的工作队列的初始状态,为负数,表示未激活状态</font></p><p style="margin: 0px 0px 0px 4px;">static final int INACTIVE&nbsp; &nbsp; &nbsp;= 1 &lt;&lt; 31;&nbsp; &nbsp; &nbsp; &nbsp;// must be negative</p><p style="margin: 0px 0px 0px 4px;">static final int SS_SEQ&nbsp; &nbsp; &nbsp; &nbsp;= 1 &lt;&lt; 16;&nbsp; &nbsp; &nbsp; &nbsp;<font color="#007fff">// 版本计数单元,SEQ和后面的UNIT含义一样,“+1”</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// Mode bits for ForkJoinPool.config and WorkQueue.config</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//工作队列的工作模式</font></p><p style="margin: 0px 0px 0px 4px;">static final int MODE_MASK&nbsp; &nbsp; = 0xffff &lt;&lt; 16;&nbsp; <font color="#007fff">// int 的高16位记录工作模式</font></p><p style="margin: 0px 0px 0px 4px;">static final int LIFO_QUEUE&nbsp; &nbsp;= 0;<span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><font color="#007fff">//默认</font></p><p style="margin: 0px 0px 0px 4px;">static final int FIFO_QUEUE&nbsp; &nbsp;= 1 &lt;&lt; 16;</p><p style="margin: 0px 0px 0px 4px;">static final int SHARED_QUEUE = 1 &lt;&lt; 31;&nbsp; &nbsp; &nbsp; &nbsp;// must be negative</p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// static fields (initialized in static initializer below)</font></p><p style="margin: 0px 0px 0px 4px;">public static final ForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory;</p><p style="margin: 0px 0px 0px 4px;">private static final RuntimePermission modifyThreadPermission;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//默认实现</font></p><p style="margin: 0px 0px 0px 4px;">static final ForkJoinPool <b>common</b>;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//common并行度,1~Max_CAP,默认为CPU核心数-1</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//可以通过系统属性“java.util.concurrent.ForkJoinPool.common.parallelism”设置</font></p><p style="margin: 0px 0px 0px 4px;">static final int <b>commonParallelism</b>;</p><p style="margin: 0px 0px 0px 4px;">private static int commonMaxSpares;</p><p style="margin: 0px 0px 0px 4px;">private static int poolNumberSequence;</p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// static configuration constants</font></p><p style="margin: 0px 0px 0px 4px;">private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec</p><p style="margin: 0px 0px 0px 4px;">private static final long TIMEOUT_SLOP = 20L * 1000L * 1000L;&nbsp; // 20ms</p><p style="margin: 0px 0px 0px 4px;">private static final int DEFAULT_COMMON_MAX_SPARES = 256;</p><p style="margin: 0px 0px 0px 4px;">private static final int SPINS&nbsp; = 0;</p><p style="margin: 0px 0px 0px 4px;">private static final int SEED_INCREMENT = 0x9e3779b9;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// Lower and upper word masks</font></p><p style="margin: 0px 0px 0px 4px;">private static final long <b>SP_MASK</b>&nbsp; &nbsp; = 0xffffffffL;&nbsp; <font color="#007fff">//低32位掩码</font></p><p style="margin: 0px 0px 0px 4px;">private static final long <b>UC_MASK</b>&nbsp; &nbsp; = ~SP_MASK; <font color="#007fff">//高32位掩码 0xffffffff00000000L</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// Active counts</font></p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; <b>AC_SHIFT</b>&nbsp; &nbsp;= 48;</p><p style="margin: 0px 0px 0px 4px;">private static final long AC_UNIT&nbsp; &nbsp; = 0x0001L &lt;&lt; AC_SHIFT; <font color="#007fff">//活跃线程数的计数单元,"+1“操作</font></p><p style="margin: 0px 0px 0px 4px;">private static final long AC_MASK&nbsp; &nbsp; = 0xffffL &lt;&lt; AC_SHIFT;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// Total counts</font></p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; <b>TC_SHIFT</b>&nbsp; &nbsp;= 32;</p><p style="margin: 0px 0px 0px 4px;">private static final long TC_UNIT&nbsp; &nbsp; = 0x0001L &lt;&lt; TC_SHIFT;</p><p style="margin: 0px 0px 0px 4px;">private static final long TC_MASK&nbsp; &nbsp; = 0xffffL &lt;&lt; TC_SHIFT;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//ctl 中索引为47的bit,控制是否可以继续创建工作者线程</font></p><p style="margin: 0px 0px 0px 4px;">private static final long <b>ADD_WORKER</b> = 0x0001L &lt;&lt; (TC_SHIFT + 15); // sign</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// runState bits: SHUTDOWN must be negative, others arbitrary powers of two</font></p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; RSLOCK&nbsp; &nbsp; &nbsp;= 1;<span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><font color="#007fff">//索引为0的bit是加锁标志位</font></p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; RSIGNAL&nbsp; &nbsp; = 1 &lt;&lt; 1;</p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; STARTED&nbsp; &nbsp; = 1 &lt;&lt; 2;</p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; STOP&nbsp; &nbsp; &nbsp; &nbsp;= 1 &lt;&lt; 29;</p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; TERMINATED = 1 &lt;&lt; 30;</p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; SHUTDOWN&nbsp; &nbsp;= 1 &lt;&lt; 31;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// Instance fields</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//控制参数</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//</font><font color="#007fff">高32位的前16位:<b>AC,活跃线程数</b></font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//高32位的后16位:<b>TC,工作线程数</b>(其中最高位作为<b>是否可以新建线程</b>的标志)</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//低32位的前16位:<b>SS,栈顶工作线程状态和版本数</b>,第1位是线程状态:1:inactive, 0:active, 后15位表示版本号,防止ABA问题</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//低32位的后16位:<b>ID,栈顶工作线程所在工作队列的索引</b>,配合WorkQueue.stackPred组成栈&nbsp;</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//即低32位记录空闲的栈顶工作线程信息,不为0即表示有空闲线程,每次提交任务如果不存在空闲的工作线程且ctl第47位不为0就会创建新线程执行提交的任务</font></p><p style="margin: 0px 0px 0px 4px;">volatile long <b>ctl</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// main pool control</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//线程池运行状态,初始为0</font></p><p style="margin: 0px 0px 0px 4px;"><span style="color: rgb(0, 127, 255); background-color: initial;">//第1位:运行状态锁标志位,防止其他线程并发修改运行状态,此bit为1则是加锁状态</span></p><p style="margin: 0px 0px 0px 4px;">volatile int <b>runState</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// lockable status</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//低16位表示并行度,高16位表示任务队列模式(默认LIFO_QUEUE)</font></p><p style="margin: 0px 0px 0px 4px;">final int <b>config</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // parallelism, mode</p><p style="margin: 0px 0px 0px 4px;">int indexSeed;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// to generate worker index</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//任务队列数组,即这里有多个队列</font></p><p style="margin: 0px 0px 0px 4px;">volatile WorkQueue[] <b>workQueues</b>;&nbsp; &nbsp; &nbsp;// main registry</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//工作者线程工厂</font></p><p style="margin: 0px 0px 0px 4px;">final ForkJoinWorkerThreadFactory <b>factory</b>;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//未捕获异常处理器</font></p><p style="margin: 0px 0px 0px 4px;">final UncaughtExceptionHandler ueh;&nbsp; // per-worker UEH</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//工作者线程的命名前缀,默认 “ForkJoinPool.commonPool-worker-”</font></p><p style="margin: 0px 0px 0px 4px;">final String <b>workerNamePrefix</b>;&nbsp; &nbsp; &nbsp; &nbsp;// to create worker name string</p><p style="margin: 0px 0px 0px 4px;">//</p><p style="margin: 0px 0px 0px 4px;">volatile AtomicLong <b>stealCounter</b>;&nbsp; &nbsp; // also used as sync monitor</p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;">private static final sun.misc.Unsafe U;</p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; ABASE;</p><p style="margin: 0px 0px 0px 4px;">private static final int&nbsp; ASHIFT;</p><p style="margin: 0px 0px 0px 4px;">private static final long CTL;</p><p style="margin: 0px 0px 0px 4px;">private static final long RUNSTATE;</p><p style="margin: 0px 0px 0px 4px;">private static final long STEALCOUNTER;</p><p style="margin: 0px 0px 0px 4px;">private static final long PARKBLOCKER;</p><p style="margin: 0px 0px 0px 4px;">private static final long QTOP;</p><p style="margin: 0px 0px 0px 4px;">private static final long QLOCK;</p><p style="margin: 0px 0px 0px 4px;">private static final long QSCANSTATE;</p><p style="margin: 0px 0px 0px 4px;">private static final long QPARKER;</p><p style="margin: 0px 0px 0px 4px;">private static final long QCURRENTSTEAL;</p><p style="margin: 0px 0px 0px 4px;">private static final long QCURRENTJOIN;</p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=10;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-480" y="200" width="440" height="1200" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontSize=10;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-3" target="KyiJdkHfAW7Gcaq_ivn_-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-3" value="testSumTask2()" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="40" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontSize=10;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-4" target="KyiJdkHfAW7Gcaq_ivn_-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-13" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;fontSize=10;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-6" target="KyiJdkHfAW7Gcaq_ivn_-12" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="500" y="310" />
<mxPoint x="500" y="230" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-4" value="SumTask2 task = new SumTask2(1, 100);" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="280" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontSize=10;" parent="1" source="froqMD3xnD5BCt7UT14n-27" target="KyiJdkHfAW7Gcaq_ivn_-10" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="380" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-6" value="ForkJoinPool pool = new <b>ForkJoinPool</b>();" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="280" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontSize=10;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="froqMD3xnD5BCt7UT14n-27" target="KyiJdkHfAW7Gcaq_ivn_-17" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="480" y="390" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-10" value="<font style="">System.out.println(sum.get());<br><font color="#007fff">同步等待获取结果</font></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="280" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-15" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontSize=10;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-12" target="KyiJdkHfAW7Gcaq_ivn_-14" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-12" value="<div>this(Math.min(MAX_CAP, Runtime.getRuntime()<span style="background-color: initial;">.availableProcessors()),</span></div><div><span style="background-color: initial;">defaultForkJoinWorkerThreadFactory, null, false);</span></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="510" y="200" width="220" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-14" value="<div style="font-size: 10px;"><div>this(checkParallelism(parallelism),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;checkFactory(factory),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;handler,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;asyncMode ? FIFO_QUEUE : <b>LIFO_QUEUE</b>,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"ForkJoinPool-" + nextPoolId() + "-worker-");</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;fontSize=10;arcSize=7;" parent="1" vertex="1">
<mxGeometry x="760" y="200" width="240" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-16" value="<div style=""><font color="#007fff"><b>parallelism 与 ctl:&nbsp;</b><br></font></div><div style="font-size: 10px;"><font color="#007fff">long np = (long)(-parallelism);<br style="font-size: 10px;"></font></div><div style="font-size: 10px;"><font color="#007fff">this.ctl = ((np &lt;&lt; AC_SHIFT) &amp; AC_MASK) | ((np &lt;&lt; TC_SHIFT) &amp; TC_MASK);</font></div><div style="font-size: 10px;"><font color="#007fff">即 this.ctl = ((np &lt;&lt; 48) &amp; 0xffffL &lt;&lt; 48) | ((np &lt;&lt; 32) &amp; 0xffffL &lt;&lt; 32);</font></div><div style="font-size: 10px;"><font color="#007fff">比如核心数8, commonPool parallelism=8-1=7, ctl = fff9fff900000000, 初始为负数</font></div><div style="font-size: 10px;"><font color="#007fff">new ForkJoinPool() 的线程池的parallelism 和核心数一样。</font></div><div style="font-size: 10px;"><font color="#ea6b66">这里为何要并行度取反?</font></div><div style="font-size: 10px;"><font color="#007fff">结合后面 tryAddWorker() 的条件,如果没有空闲的工作者线程且ctl索引为47的位不为0才可以创建线程,</font></div><div style="font-size: 10px;"><font color="#007fff">以commonPool为例将并行度取反即 fff9,每次新建线程TC加“1”,加“7”之后索引为47的位将变为0,将不能创建新线程,推理可以创建7个工作者线程</font></div>" style="text;html=1;align=left;verticalAlign=top;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1010" y="200" width="680" height="120" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-20" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-17" target="KyiJdkHfAW7Gcaq_ivn_-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-17" value="<b>externalPush</b>(job);<br style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">任务提交的统一方法,其他<b>execute</b>() <b>invoke</b>() 等方法都是简单封装的这个方法</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="520" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-19" target="KyiJdkHfAW7Gcaq_ivn_-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-19" value="一个复杂的判断条件处理<br><font color="#007fff">暂略</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="760" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-21" target="KyiJdkHfAW7Gcaq_ivn_-23" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-21" value="externalSubmit(task);" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="760" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-23" target="KyiJdkHfAW7Gcaq_ivn_-25" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-23" value="<b>r = ThreadLocalRandom.getProbe();</b><br><font color="#007fff"><b>线程探针</b>未初始化就执行初始化并返回<br>用到其散列特性<br></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1000" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-25" target="KyiJdkHfAW7Gcaq_ivn_-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-25" value="for(::)<br><font color="#007fff"><b>一个提交操作可能涉及几次循环<br></b>任务提交到工作队列后返回<br>比如初始提交第一个任务:涉及工作队列数组初始化、创建工作队列、提交任务到队列<br></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1000" y="521" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-31" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-27" target="KyiJdkHfAW7Gcaq_ivn_-29" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1380" y="551" />
<mxPoint x="1380" y="390" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-32" value="<font style="font-size: 10px;"><font color="#007fff">(rs = runState) &lt; 0<br>即关闭状态</font><br></font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-31" vertex="1" connectable="0">
<mxGeometry x="-0.0429" y="2" relative="1" as="geometry">
<mxPoint x="82" y="12" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-34" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-27" target="KyiJdkHfAW7Gcaq_ivn_-33" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1380" y="551" />
<mxPoint x="1380" y="470" />
<mxPoint x="1560" y="470" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-36" value="<font color="#007fff" style="font-size: 10px;">未启动或<br>任务队列未初始化</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-34" vertex="1" connectable="0">
<mxGeometry x="0.453" y="-4" relative="1" as="geometry">
<mxPoint x="-24" y="16" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-43" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-27" target="KyiJdkHfAW7Gcaq_ivn_-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-44" value="<div><font color="#007fff" style="font-size: 10px;">(q = ws[k = r &amp; m &amp; SQMASK]) != null</font></div><div><font color="#007fff"><span style="font-size: 10px;">即通过线程探针值选取的<b>偶数队列</b>不为空</span></font></div><div><font color="#007fff"><span style="font-size: 10px;">即队列已经创建了</span></font></div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-43" vertex="1" connectable="0">
<mxGeometry x="0.0346" y="-3" relative="1" as="geometry">
<mxPoint x="7" y="26" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-46" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-27" target="KyiJdkHfAW7Gcaq_ivn_-45" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1380" y="551" />
<mxPoint x="1380" y="810" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-47" value="<font color="#007fff">((rs = runState) &amp; RSLOCK) == 0</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-46" vertex="1" connectable="0">
<mxGeometry x="0.3214" y="-3" relative="1" as="geometry">
<mxPoint x="66" y="7" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-51" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-27" target="KyiJdkHfAW7Gcaq_ivn_-50" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1380" y="551" />
<mxPoint x="1380" y="890" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-53" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-27" target="KyiJdkHfAW7Gcaq_ivn_-52" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-27" value="线程池运行状态" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1240" y="521" width="120" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-29" value="tryTerminate(false, false);<br>throw new RejectedExecutionException();" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1560" y="361" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-30" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>WorkQueue</b></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">任务队列,ForkJoinPool一共有大于等于并行度的2的指数幂×2个任务队列,存储ForkJoinTask类型任务,初始化容量是8192</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><br></font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//初始化容量</font></p><p style="margin: 0px 0px 0px 4px;">static final int INITIAL_QUEUE_CAPACITY = 1 &lt;&lt; 13;&nbsp; //8192</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//最大容量</font></p><p style="margin: 0px 0px 0px 4px;">static final int MAXIMUM_QUEUE_CAPACITY = 1 &lt;&lt; 26; // 64M<br></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//&lt;0未激活,为奇数时表示处于扫描状态,为偶数时表示为繁忙(看源码应该是正在执行队列中的任务)</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//从源码可以看到</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//1) 创建线程时会注册新的工作队列,scanState</font><span style="color: rgb(0, 127, 255); background-color: initial;">记录此工作队列插入工作队列数组的索引,是奇数位置</span></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//2) 提交任务时,可能会创建工作队列并放在工作队列数组的偶数位置,且工作队列scanState初始为INACTIVE</font>&nbsp; &nbsp;&nbsp;</p><p style="margin: 0px 0px 0px 4px;">volatile int <b>scanState</b>;<span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span>// &lt;0: inactive; odd:scanning&nbsp;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//前一个工作队列在工作队列数组中的索引,单数索引工作队列中包含绑定的工作线程,</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">通过这个字段将工作者线程连接起来,从访问方式上看其实是组成一个<b>栈</b>的结构,栈顶在ForkJoinPool ctl ID段,</font><span style="color: rgb(0, 127, 255); background-color: initial;">唤醒工作者线程时总是从栈顶开始唤醒</span></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">每一个线程在挂起时都会持有前一个等待线程所在工作队列的索引,由此构成一个等待的工作线程栈,栈顶是最新的等待的线程</font></p><p style="margin: 0px 0px 0px 4px;">int <b>stackPred</b>;&nbsp; &nbsp; <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>// pool stack (ctl) predecessor</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//偷取的任务数量,任务偷取并不是将任务存到这个工作队列而是直接由工作者线程执行</font></p><p style="margin: 0px 0px 0px 4px;">int <b>nsteals</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// number of steals</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//随机数种子</font></p><p style="margin: 0px 0px 0px 4px;">int <b>hint</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>// randomization and stealer index hint&nbsp;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//任务队列在队列数组中的索引以及队列模式(FIFO | FILO)</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//高16位是队列模式(<b>LIFO</b>:0&lt;&lt;16 FIFO: 1&lt;&lt;16),低16位是最近插入工作队列数组的索引位置</font></p><p style="margin: 0px 0px 0px 4px;">int <b>config</b>; <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="">&nbsp; &nbsp;</span></span></p><p style="margin: 0px 0px 0px 4px;"><span style=""><span style=""><font color="#007fff">//队列锁,控制多个线程往队列中同步地提交任务</font></span></span></p><p style="margin: 0px 0px 0px 4px;">volatile int <b>qlock</b>;<span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>// 1: locked, &lt; 0: terminate; else 0</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//poll操作(即取任务)的下个位置索引,初始是规定容量的一半,即4096</font></p><p style="margin: 0px 0px 0px 4px;">volatile int <b>base</b>;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//push操作(即添加任务)的下个位置索引,初始是规定容量的一半,即4096</font><br></p><p style="margin: 0px 0px 0px 4px;">int <b>top</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//任务数组,创建队列时,数组为null,首次提交任务时才实例化数组<br></font></p><p style="margin: 0px 0px 0px 4px;">ForkJoinTask&lt;?&gt;[] <b>array</b>; <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></p><p style="margin: 0px 0px 0px 4px;">final ForkJoinPool <b>pool</b>;&nbsp; &nbsp;<span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>// the containing pool (may be null)</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//创建工作者线程时创建的工作队列,会使用owner保存绑定的ForkJoinWorkerThread</font></p><p style="margin: 0px 0px 0px 4px;">final ForkJoinWorkerThread <b>owner</b>; // owning thread or null if shared</p><p style="margin: 0px 0px 0px 4px;">volatile Thread <b>parker</b>;&nbsp; &nbsp; <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>// == owner during call to park; else null</p><p style="margin: 0px 0px 0px 4px;">volatile ForkJoinTask&lt;?&gt; <b>currentJoin</b>;<span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>// task being joined in awaitJoin</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//当前偷取的任务</font></p><p style="margin: 0px 0px 0px 4px;">volatile ForkJoinTask&lt;?&gt; <b>currentSteal</b>; <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>// mainly used by helpStealer&nbsp;</p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=10;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-960" y="200" width="440" height="560" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-40" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-33" target="KyiJdkHfAW7Gcaq_ivn_-39" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-33" value="工作队列数组初始化<br><font color="#007fff">在<b>RSLOCK</b>锁同步下创建工作队列数组(工作队列仍为初始化),然后修改运行状态为STARTED</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1560" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-35" value="<font style="font-size: 10px;"><br></font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="1" vertex="1" connectable="0">
<mxGeometry x="1430.0000000000005" y="430.0033333333335" as="geometry">
<mxPoint x="-7" y="72" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-39" value="U.compareAndSwapObject(this, <b>STEALCOUNTER</b>, null,new AtomicLong());<br>workQueues = new <b>WorkQueue</b>[n];<br>ns = <b>STARTED</b>;<br><font color="#007fff">本地CPU核心数8,实际并行度是7, 最终创建的工作队列个数是16</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1800" y="430" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-41" value="<div style="font-size: 10px;"><font style="font-size: 10px;"><b style="">RSLOCK锁的实现(lockRunState())</b><b style="">:</b></font></div><div style="font-size: 10px;"><font style="font-size: 10px;">借助UNSAFE CAS 接口实现</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">加锁:判断runState锁标志位是否加锁(1加锁0未加锁),已经加锁就自旋等待其他线程释放锁,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">未加锁则CAS修改标志位为1</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">解锁:CAS修改标志位为0</font></div><div style="font-size: 10px;"><font style="font-size: 10px;"><b>计算工作队列个数算法</b>:</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">int p = 8; //比如并行度设置为8</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">int n = (p &gt; 1) ? p - 1 : 1;</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">n |= n &gt;&gt;&gt; 1; n |= n &gt;&gt;&gt; 2;&nbsp; n |= n &gt;&gt;&gt; 4;</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">n |= n &gt;&gt;&gt; 8; n |= n &gt;&gt;&gt; 16; n = (n + 1) &lt;&lt; 1;</font></div><div style="font-size: 10px;"><font style="font-size: 10px;">写个测试跑一下, 参考测试用例:testGenerateWorkQueueArraySize(),或者用1024画一画<br>会很明显地看出就是求<b style="">大于等于并行度</b><b style="">的最小2的指数幂的2倍</b>, <br>比如: 大于等于6的2的指数幂最小是8, 再乘以2就是16</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=8;fontColor=#3399FF;" parent="1" vertex="1">
<mxGeometry x="2000" y="305" width="450" height="170" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-42" target="KyiJdkHfAW7Gcaq_ivn_-58" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-42" value="提交任务到队列<br><font color="#007fff">在<b>队列锁qlock</b>同步下提交<br><b>其他分支都是为这个分支服务的</b><br></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="1560" y="521" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-49" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-45" target="KyiJdkHfAW7Gcaq_ivn_-48" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-45" value="创建工作队列<br><font color="#007fff">在<b>RSLOCK</b>锁同步下创建工作队列</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1560" y="780" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-57" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-48" target="KyiJdkHfAW7Gcaq_ivn_-56" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-48" value="<div>q = new <b>WorkQueue</b>(this, null);</div><div>q.hint = r;</div><div>q.config = k | <b>SHARED_QUEUE</b>;</div><div>q.<b>scanState</b> = <b>INACTIVE</b>;</div><div><font color="#007fff">这里可以看到创建的是偶数索引的队列</font></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1800" y="780" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-50" value="move= true;<br><font color="#007fff">走到这里基本都是因为取不到锁,需要尝试换一个工作队列提交</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1560" y="860" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-55" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-52" target="KyiJdkHfAW7Gcaq_ivn_-54" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-67" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-55" vertex="1" connectable="0">
<mxGeometry x="-0.0125" y="1" relative="1" as="geometry">
<mxPoint y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-52" value="move == true ?" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1240" y="940" width="120" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-54" value="r = ThreadLocalRandom.advanceProbe(r);<br><font color="#007fff">更新线程探针值</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1560" y="940" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-56" value="<div>if (rs &gt; 0 &amp;&amp;&nbsp; (ws = workQueues) != null &amp;&amp;</div><div>k &lt; ws.length &amp;&amp; ws[k] == null)</div><div><b>ws[k] = q;&nbsp;</b></div><div><font color="#007fff">把工作队列注册到队列数组</font></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1800" y="860" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-58" target="KyiJdkHfAW7Gcaq_ivn_-60" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-65" value="<font color="#007fff">成功</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-61" vertex="1" connectable="0">
<mxGeometry x="-0.2" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-63" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-58" target="KyiJdkHfAW7Gcaq_ivn_-62" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-64" value="<font color="#007fff">失败</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-63" vertex="1" connectable="0">
<mxGeometry x="0.0244" y="3" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-58" value="if (q.<b>qlock</b> == 0 &amp;&amp; U.<b>compareAndSwapInt</b>(q, QLOCK, 0, 1)) {...}<br><font color="#007fff">先尝试通过CAS获取队列锁 qlock</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1800" y="521" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-69" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-60" target="KyiJdkHfAW7Gcaq_ivn_-68" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-60" value="<div>if ((a != null &amp;&amp; a.length &gt; s + 1 - q.base) ||</div><div>&nbsp; &nbsp; (a = q.<b>growArray</b>()) != null) {</div><div><font color="#007fff">&nbsp; &nbsp; //计算插入位置</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; int j = (((a.length - 1) &amp; s) &lt;&lt; ASHIFT) + ABASE;</font></div><div style="font-size: 9px;">&nbsp; &nbsp; U.<b>putOrderedObject</b>(a, j, task);</div><div>&nbsp; &nbsp; U.<b>putOrderedInt</b>(q, QTOP, s + 1);</div><div>&nbsp; &nbsp; submitted = true;</div><div>}</div><div><font color="#007fff">growArray() 实现q.array的初始化以及扩容</font></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=7;" parent="1" vertex="1">
<mxGeometry x="2040" y="496.25" width="240" height="109.5" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-62" value="move = true;&nbsp;<br><font color="#007fff">方法最后面会更新线程探针值,下一次循环大概率会换一个工作队列</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1800" y="620" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-71" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-68" target="KyiJdkHfAW7Gcaq_ivn_-70" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-68" value="<div>finally:</div><div>U.compareAndSwapInt(q, QLOCK, 1, 0);</div><font color="#007fff">通过CAS释放队列锁 qlock</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;" parent="1" vertex="1">
<mxGeometry x="2060" y="620" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-75" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-70" target="KyiJdkHfAW7Gcaq_ivn_-72" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2280" y="730" />
<mxPoint x="2280" y="1020" />
<mxPoint x="740" y="1020" />
<mxPoint x="740" y="1070" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-70" value="if (submitted) {<br><font color="#007fff">&nbsp; &nbsp; //ws是工作队列数组,q是任务插入的队列</font><br><div>&nbsp; &nbsp; <b>signalWork</b>(ws, q);&nbsp;</div><div>&nbsp; &nbsp; <b>return</b>; <font color="#007fff">//退出for(;;)</font><br>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=10;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="2060" y="700" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-74" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-72" target="KyiJdkHfAW7Gcaq_ivn_-73" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-72" value="<b>signalWork</b>(ws, q);<br><font color="#007fff"><b>唤醒工作者线程处理任务</b>,首次执行会创建工作者线程并启动,当扫描到多个任务工作者线程还会唤醒其他线程帮忙处理</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="760" y="1040" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-77" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-73" target="KyiJdkHfAW7Gcaq_ivn_-79" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1240.0000000000005" y="1070" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-78" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;fillColor=#d5e8d4;strokeColor=#82b366;dashed=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-73" target="KyiJdkHfAW7Gcaq_ivn_-16" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1220" y="1040" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-73" value="while ((<b>c</b> = <b>ctl</b>) &lt; 0L)<br><font color="#007fff">和上面的<b>for(;;)</b>类似,一个唤醒操作可能涉及<b>几次循环</b>,由ctl初始化过程可知开始必定是负数&nbsp;</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1000" y="1040" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-81" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-82" target="KyiJdkHfAW7Gcaq_ivn_-80" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-85" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-81" vertex="1" connectable="0">
<mxGeometry x="-0.2922" y="2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-91" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-79" target="KyiJdkHfAW7Gcaq_ivn_-90" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-16" value="<font color="#007fff" style="font-size: 10px;">有空闲线程<br style="font-size: 10px;">就用空闲线程处理<br style="font-size: 10px;"></font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;" parent="KyiJdkHfAW7Gcaq_ivn_-91" vertex="1" connectable="0">
<mxGeometry x="0.2033" relative="1" as="geometry">
<mxPoint y="4" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-15" style="rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;fillColor=#d5e8d4;strokeColor=#82b366;entryX=0.77;entryY=-0.022;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-79" target="froqMD3xnD5BCt7UT14n-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-79" value="(sp = (int)c) == 0<br><font color="#007fff">long型的c转int<br>就是读取低32位</font>" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1240" y="1040" width="120" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-93" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-135" target="KyiJdkHfAW7Gcaq_ivn_-92" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-80" value="&nbsp;<b>tryAddWorker</b>(c);<br><font style="font-size: 9px;" color="#007fff">ctl 低32位为0,且index=47的bit为1, 就新增工作者线程,</font><font style="font-size: 9px;" color="#007fff">index=47的bit 控制是否可以新建工作者线程</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1560" y="1040" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-83" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-79" target="KyiJdkHfAW7Gcaq_ivn_-82" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1360" y="1071" as="sourcePoint" />
<mxPoint x="1560" y="1070" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-84" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-83" vertex="1" connectable="0">
<mxGeometry x="0.0083" y="2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-89" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-82" target="KyiJdkHfAW7Gcaq_ivn_-88" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-17" style="rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.775;entryY=-0.008;entryDx=0;entryDy=0;entryPerimeter=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-82" target="froqMD3xnD5BCt7UT14n-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-82" value="(c &amp; <font style="font-size: 9px;">ADD_WORKER</font>)<br>&nbsp;!= 0L<br><font color="#007fff">ctl中索引为47的bit<br>不为0</font>" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1400" y="1040" width="120" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-88" value="break;<br><font color="#007fff">没有空闲线程且线程数量已达到最大值,不处理</font>" style="whiteSpace=wrap;html=1;fontSize=10;rounded=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1400" y="1120" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-95" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-90" target="KyiJdkHfAW7Gcaq_ivn_-94" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-96" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-95" vertex="1" connectable="0">
<mxGeometry x="-0.1167" y="-2" relative="1" as="geometry">
<mxPoint x="-7" y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-98" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-90" target="KyiJdkHfAW7Gcaq_ivn_-97" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-90" value="ws == null<br><font color="#007fff">前面已经初始化的工作队列数组又变成null, 基本是线程池被关闭了</font>" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1240" y="1179" width="120" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-132" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-92" target="KyiJdkHfAW7Gcaq_ivn_-131" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-92" value="<font style=""><div style=""><div style="">long <b>nc</b> = ((AC_MASK &amp; (c + AC_UNIT)) |</div><div style="">(TC_MASK &amp; (c + TC_UNIT)));</div><div style=""><font color="#007fff">nc 是 "new ctl" 的意思,bit48-63 "+1”,bit32-47也 “+1”,即用于<b>更新 ctl 活跃线程数和工作线程总数</b></font></div></div></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2040" y="1040" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-94" value="break;<br><font color="#007fff">直接退出</font>" style="whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1400" y="1187.5" width="120" height="42" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-99" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-97" target="KyiJdkHfAW7Gcaq_ivn_-94" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-100" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-99" vertex="1" connectable="0">
<mxGeometry x="-0.766" y="-1" relative="1" as="geometry">
<mxPoint x="-4" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-103" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-97" target="KyiJdkHfAW7Gcaq_ivn_-102" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-97" value="ws.length &lt;= <br>(i = sp &amp; SMASK)<br><font color="#007fff">sp是ctl低32位,取其低16位,即<b>i是栈顶工作队列的索引</b></font>" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1240" y="1261.5" width="120" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-106" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-102" target="KyiJdkHfAW7Gcaq_ivn_-94" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-107" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-106" vertex="1" connectable="0">
<mxGeometry x="-0.9098" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-109" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-102" target="KyiJdkHfAW7Gcaq_ivn_-111" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1300.0000000000005" y="1485" as="targetPoint" />
<Array as="points">
<mxPoint x="1300" y="1420" />
<mxPoint x="1340" y="1420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-110" value="<font color="#007fff">即<b>栈顶</b>工作队列<br>和线程就绪<br></font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-109" vertex="1" connectable="0">
<mxGeometry x="-0.2671" y="-1" relative="1" as="geometry">
<mxPoint x="15" y="19" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-102" value="(v = ws[i]) == null<br><font color="#007fff">基本是线程池正在关闭</font>" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1240" y="1340" width="120" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-104" value="" style="shape=curlyBracket;whiteSpace=wrap;html=1;rounded=1;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;" parent="1" vertex="1">
<mxGeometry x="1220" y="1179" width="10" height="221" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-105" value="<font color="#007fff" style="font-size: 10px;">检查工作队列数组、工作队列是否正常</font>" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="1090" y="1274.5" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-119" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-111" target="KyiJdkHfAW7Gcaq_ivn_-118" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-111" value="<div><font color="#007fff" size="1">//即 (sp + 1&lt;&lt;16) &amp; ~(1&lt;&lt;31),即修改线程状态为active,以及SS+“1”,更新版本号</font></div><div><font size="1">int <b>vs</b> = (sp + SS_SEQ) &amp; ~INACTIVE;</font></div><div><font size="1">int d = sp - v.scanState; <font color="#007fff">//?</font></font></div><div><font size="1">long <b>nc</b> = (UC_MASK &amp; (c + AC_UNIT)) | (SP_MASK &amp; v.stackPred);</font></div><div><font color="#007fff" size="1">sp是ctl低32位,v 是ws[i]即栈顶工作队列</font></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;strokeColor=#000000;fontColor=#000000;arcSize=8;" parent="1" vertex="1">
<mxGeometry x="1240" y="1462.5" width="200" height="97.5" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-121" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-118" target="KyiJdkHfAW7Gcaq_ivn_-122" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1480.0000000000005" y="1612.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-123" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-121" vertex="1" connectable="0">
<mxGeometry x="-0.1889" y="-1" relative="1" as="geometry">
<mxPoint x="6" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-125" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-118" target="KyiJdkHfAW7Gcaq_ivn_-124" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-118" value="d == 0 &amp;&amp; U.<b>compareAndSwapLong</b>(<br>this, CTL, c, nc)" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;align=center;strokeColor=#000000;fontColor=#000000;rounded=1;arcSize=13;" parent="1" vertex="1">
<mxGeometry x="1260" y="1580" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-122" value="<font size="1">v.scanState = vs;<br>if ((p = v.parker) != null)<br>U.<b>unpark</b>(p);<br>break;<br><font color="#007fff">即唤醒队列的owner工作者线程</font><br></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1560" y="1580" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-127" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-124" target="KyiJdkHfAW7Gcaq_ivn_-126" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-128" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="KyiJdkHfAW7Gcaq_ivn_-127" vertex="1" connectable="0">
<mxGeometry x="0.0132" relative="1" as="geometry">
<mxPoint x="-20" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-124" value="q != null &amp;&amp; q.base == q.top<br><font color="#007fff">没有更多待执行的任务</font>" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;align=center;strokeColor=#000000;fontColor=#000000;rounded=1;arcSize=13;" parent="1" vertex="1">
<mxGeometry x="1260" y="1661" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-126" value="break;<br><font color="#007fff">没有更多待执行的任务<br>就直接退出<br></font>" style="whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1600" y="1670" width="120" height="42" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-129" value="<font color="#007fff" style="font-size: 10px;">CAS锁</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1190" y="1595" width="50" height="30" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-134" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-131" target="KyiJdkHfAW7Gcaq_ivn_-133" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-131" value="<font style=""><div style=""><div style="">add = U.compareAndSwapLong(this, CTL, c, nc);<br></div><div style=""><font color="#007fff">lockRunState()锁同步下更新ctl</font></div></div></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2040" y="1121" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-139" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-133" target="KyiJdkHfAW7Gcaq_ivn_-138" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-133" value="<font style=""><div style=""><div style=""><div style="">if (add) {</div><div><b>&nbsp; &nbsp; createWorker();</b></div><div>&nbsp; &nbsp; break;</div><div>}</div></div></div></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2040" y="1200.5" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-136" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-80" target="KyiJdkHfAW7Gcaq_ivn_-135" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1760" y="1070" as="sourcePoint" />
<mxPoint x="2040" y="1070" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-135" value="<font style=""><div style=""><div style="">do {...}</div><div style="">while (((c = ctl) &amp; ADD_WORKER) != 0L &amp;&amp; (int)c == 0)<br></div><div style=""><font color="#007fff">检查是否可以创建线程</font></div><div style=""><font color="#007fff">(int)c == 0 即ctl低32位为0,是最初时的状态</font></div></div></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1800" y="1040" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-137" value="<font color="#007fff" style="font-size: 10px;">这里的意思是最初创建线程时,<br><b>如果失败会一直自旋重试</b>,<br style="font-size: 10px;">但是后面再创建线程就不会自旋重试了</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1800" y="1110" width="190" height="50" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-141" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-138" target="KyiJdkHfAW7Gcaq_ivn_-140" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-143" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-138" target="KyiJdkHfAW7Gcaq_ivn_-142" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-165" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;fillColor=#d5e8d4;strokeColor=#000000;dashed=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-138" target="KyiJdkHfAW7Gcaq_ivn_-164" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2260" y="1261" />
<mxPoint x="2260" y="1780" />
<mxPoint x="860" y="1780" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-138" value="<div style=""><div style=""><div style="">wt = fac.<b>newThread</b>(this);<br></div><div style="">wt.<b>start</b>();<br></div><div style="color: rgb(0, 127, 255);">使用ForkJoinWorkerThreadFactory创建工作者线程并启动,启动成功之后返回true</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="2280" y="1200.5" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-140" value="<div style=""><div style=""><div style=""><b>deregisterWorker</b>(wt, ex);<br></div><div style="">return false;<br></div><div style="color: rgb(0, 127, 255);">如果线程启动时出现异常,注销线程并返回false</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;" parent="1" vertex="1">
<mxGeometry x="2280" y="1280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-147" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-142" target="KyiJdkHfAW7Gcaq_ivn_-146" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-142" value="<div style=""><div style=""><div style="">return new <b>ForkJoinWorkerThread</b>(pool, null);<br></div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="2520" y="1200.5" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-145" value="CommonPoolForkJoinWorkerThreadFactory<br>(commonPool默认的线程工厂)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2510" y="1165.5" width="220" height="40" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-150" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-146" target="KyiJdkHfAW7Gcaq_ivn_-149" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2980" y="1230" />
<mxPoint x="2980" y="1360" />
<mxPoint x="2020" y="1360" />
<mxPoint x="2020" y="1411" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-146" value="<div style=""><div style=""><div style=""><div>super("aForkJoinWorkerThread");</div><div>U.<b>putOrderedObject</b>(this, INHERITEDACCESSCONTROLCONTEXT, INNOCUOUS_ACC);</div><div>this.<b>pool</b> = pool;</div><div>this.<b>workQueue</b>=pool.<b>registerWorker</b>(this);</div></div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=6;" parent="1" vertex="1">
<mxGeometry x="2760" y="1180" width="200" height="100" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-148" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ForkJoinWorkerThread </b>extends Thread<br></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">ForkJoinPool 的工作者线程实现</font></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><br></font></p><p style="margin: 0px 0px 0px 4px;">final ForkJoinPool <b>pool</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the pool this thread works in</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//这个工作队列是工作者线程初始化时创建的</font></p><p style="margin: 0px 0px 0px 4px;">final ForkJoinPool.WorkQueue <b>workQueue</b>; // work-stealing mechanics</p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;">private static final sun.misc.Unsafe U;</p><p style="margin: 0px 0px 0px 4px;">private static final long THREADLOCALS;</p><p style="margin: 0px 0px 0px 4px;">private static final long INHERITABLETHREADLOCALS;</p><p style="margin: 0px 0px 0px 4px;">private static final long INHERITEDACCESSCONTROLCONTEXT;</p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=10;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-960" y="840" width="440" height="199" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-153" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-149" target="KyiJdkHfAW7Gcaq_ivn_-152" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-149" value="<div style=""><div style=""><div style="">ForkJoinPool#<b>registerWorker</b>(</div><div style="">ForkJoinWorkerThread wt)</div><div style=""><font color="#007fff">主要就是将工作者线程放到了工作队列的owner字段</font></div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;arcSize=14;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="2040" y="1381.75" width="200" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-155" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-152" target="KyiJdkHfAW7Gcaq_ivn_-158" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2380.782608695653" y="1462.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-152" value="<div style=""><div style=""><div style="">wt.<b>setDaemon</b>(true);<br></div><div style="">wt.<b>setUncaughtExceptionHandler</b>(handler);<br></div><div style="">WorkQueue w = new <b>WorkQueue</b>(this, wt);<br></div><div style=""><font color="#007fff">这里可以看到<b>创建工作者线程的时候还创建了工作队列,这个工作队列是和线程绑定的</b></font></div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;arcSize=14;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2280.75" y="1381.25" width="200" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-157" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-158" target="KyiJdkHfAW7Gcaq_ivn_-156" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-156" value="<div style=""><div style=""><div style="">wt.<b>setName</b>(workerNamePrefix.concat(</div><div style="">Integer.toString(i &gt;&gt;&gt; 1)));<br></div><div style=""><font color="#007fff">修改工作者线程名称,</font><font color="#007fff">&nbsp;"ForkJoinPool-" + nextPoolId() + "-worker-" + 任务队列索引&gt;&gt;&gt;1</font></div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;arcSize=14;" parent="1" vertex="1">
<mxGeometry x="2280.75" y="1721" width="200" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-162" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-158" target="KyiJdkHfAW7Gcaq_ivn_-161" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-158" value="<div style=""><div style=""><div style="">锁同步控制下</div><div style="">将与工作者线程绑定的工作队列注册到线程池的工作队列数组中</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;arcSize=14;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="2280.75" y="1551" width="200" height="59" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-160" value="<font color="#007fff" style="font-size: 10px;">创建工作者线程时会创建一个与线程绑定的工作队列,两者通过下面两个字段相互绑定:<br style="font-size: 10px;">ForkJoinWokerThread.workQueue;<br style="font-size: 10px;">WorkQueue.owner;</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="-960" y="775" width="410" height="50" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-176" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-161" target="KyiJdkHfAW7Gcaq_ivn_-174" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2700" y="1800" />
<mxPoint x="1460" y="1800" />
<mxPoint x="1460" y="1960" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-161" value="<div style=""><div style=""><div style=""><div>int i = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // assign a pool index</div><div>int <b>mode</b> = config &amp; MODE_MASK;</div><div>int rs = lockRunState();</div><div>try {</div><div>&nbsp; &nbsp; WorkQueue[] ws; int n;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // skip if no array</div><div>&nbsp; &nbsp; if ((<b>ws</b> = workQueues) != null &amp;&amp; (n = ws.length) &gt; 0) {</div><div><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; //下面三行代码用于计算工作队列插入位置</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; int s = indexSeed += SEED_INCREMENT;&nbsp; // unlikely to collide</div><div>&nbsp; &nbsp; &nbsp; &nbsp; int m = n - 1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; i = ((s &lt;&lt; 1) | 1) &amp; m;&nbsp; <font color="#007fff">//最后一位置1,即插入索引为奇数的位置, 初始值为3</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (ws[i] != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <font color="#007fff">//此槽位已经有工作队列了</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int probes = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// step by approx half n</div><div><font color="#007fff"><span style="white-space: pre;">	</span>&nbsp; &nbsp; //从当前位置步进 (n&gt;&gt;&gt;1) &amp; EVENMASK + 2, 选择下一个奇数位置</font></div><div><font color="#007fff"><span style="white-space: pre;">	</span>&nbsp; &nbsp; //直到找到空槽<br></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int step = (n &lt;= 4) ? 2 : ((n &gt;&gt;&gt; 1) &amp; EVENMASK) + 2;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (ws[i = (i + step) &amp; m] != null) {</div><div><font color="#007fff"><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>//试过所有奇数位置都没有空槽,就对工作队列进行扩容一倍</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (++probes &gt;= n) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; workQueues = ws = Arrays.copyOf(ws, n &lt;&lt;= 1);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m = n - 1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; probes = 0;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; w.<b>hint</b> = s;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><font color="#007fff">// 记录随机种子s</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; w.<b>config</b> = i | mode;<span style="white-space: pre;">	</span><font color="#007fff">// 更新最近插入工作队列数组的奇数位置</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; w.<b>scanState</b> = i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // publication fence</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <b>ws[i] = w</b>;<span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><font color="#007fff">// 将与工作者线程绑定的工作队列插入工作队列数组空槽</font></div><div>&nbsp; &nbsp; }</div><div>} finally {</div><div>&nbsp; &nbsp; unlockRunState(rs, rs &amp; ~RSLOCK);</div><div>}</div></div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=1;" parent="1" vertex="1">
<mxGeometry x="2520" y="1381.75" width="360" height="398.25" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-163" value="这里其实类似解决哈希冲突的<b>开放地址法(线性探测再哈希)</b><br>比如:队列数组length = 16, i = 1,<br style="font-size: 10px;">ws[1] 已经有工作队列的话,下次步进获取的奇数位置是11:<br style="font-size: 10px;">step = ((16&gt;&gt;&gt;1 &amp;&nbsp;0xfffe) + 2 = 10;<br style="font-size: 10px;">i = (1 + 10) &amp; 15 = 11;<br style="font-size: 10px;">下次步进:<br style="font-size: 10px;">5<br style="font-size: 10px;">15<br style="font-size: 10px;">9<br style="font-size: 10px;">3<br style="font-size: 10px;">13<br style="font-size: 10px;">7<br style="font-size: 10px;">1<br style="font-size: 10px;">11<br style="font-size: 10px;">5<br style="font-size: 10px;">..." style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#007FFF;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2890" y="1455.87" width="290" height="210" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-167" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-164" target="KyiJdkHfAW7Gcaq_ivn_-166" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-164" value="<div><b>ForkJoinPoolThread$run()</b></div><div><b><font color="#007fff">工作者线程执行</font></b></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="760" y="1800" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-169" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-166" target="KyiJdkHfAW7Gcaq_ivn_-168" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-166" value="onStart();<br><font color="#007fff">用于拓展,默认是空的</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1000" y="1800" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-171" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-168" target="KyiJdkHfAW7Gcaq_ivn_-170" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-173" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-168" target="KyiJdkHfAW7Gcaq_ivn_-172" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-168" value="pool.<b>runWorker</b>(workQueue);<br><font color="#007fff">workQueue是和工作者线程绑定的工作队列<br>即<b>先扫描与本线程绑定的工作队列中的任务</b><br></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1000" y="1880" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-170" value="finally:<br>onTermination(exception);<br>pool.deregisterWorker(this, exception);<br><font color="#007fff">即退出工作者线程的操作</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1000" y="1960" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-175" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-172" target="KyiJdkHfAW7Gcaq_ivn_-174" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-172" value="w.growArray();<br><font color="#007fff">前面只是创建了绑定的工作队列,但是并没有进行初始化,growArray是初始化或扩容,这里是初始化</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1240" y="1880" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-180" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-174" target="KyiJdkHfAW7Gcaq_ivn_-179" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-174" value="int seed = w.hint;<br>int r = (seed == 0) ? 1 : seed;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1240" y="1960" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-12" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-179" target="nZumD_jCBZHTr2Y5oNFb-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="KyiJdkHfAW7Gcaq_ivn_-179" value="for (ForkJoinTask&lt;?&gt; t;;)" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1240" y="2040" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-4" value="N" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-1" target="nZumD_jCBZHTr2Y5oNFb-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-6" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-1" target="nZumD_jCBZHTr2Y5oNFb-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-7" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="nZumD_jCBZHTr2Y5oNFb-6" vertex="1" connectable="0">
<mxGeometry x="-0.0533" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-1" value="t != null" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1500" y="2140" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-9" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-3" target="nZumD_jCBZHTr2Y5oNFb-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-10" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="nZumD_jCBZHTr2Y5oNFb-9" vertex="1" connectable="0">
<mxGeometry x="-0.1867" relative="1" as="geometry">
<mxPoint x="5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-3" value="<font style="font-size: 10px;" color="#007fff">被正常唤醒</font>" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-3" target="NMrCZGO8tHE7oQIJTHmH-2" edge="1">
<mxGeometry x="0.408" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-11" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-3" target="froqMD3xnD5BCt7UT14n-9" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1620" y="2300" />
<mxPoint x="1700" y="2300" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-3" value="!<b>awaitWork</b>(w, r)<br>" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1500" y="2230" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-11" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-5" target="NMrCZGO8tHE7oQIJTHmH-10" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-5" value="w.runTask(t);<br><font color="#007fff">当前工作线程执行扫描到的任务</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1720" y="2140" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-8" value="break;<br><font color="#007fff">被终止就直接退出循环</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1720" y="2230" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-13" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-11" target="nZumD_jCBZHTr2Y5oNFb-1" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nZumD_jCBZHTr2Y5oNFb-11" value="t =&nbsp;<b style="border-color: var(--border-color);">scan</b>(w, r)<br><font color="#007fff">扫描待执行的任务(工作窃取),<b>如果有多个待处理任务还会唤醒其他线程协助处理剩下的可执行任务</b></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="1480" y="2040" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-9" value="<font style="font-size: 10px;"><font color="#007fff">这部分逻辑细节有点复杂</font><br><font color="#007fff">不太适合画图</font><br><font color="#ff6666">还有些细节没梳理完,<br>但是浪费太多时间了,先放一下</font><br></font>" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.005;entryY=0.264;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="nZumD_jCBZHTr2Y5oNFb-11" target="NMrCZGO8tHE7oQIJTHmH-8" edge="1">
<mxGeometry x="-0.0008" relative="1" as="geometry">
<mxPoint x="1900" y="2070" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-4" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;dashed=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-2" target="nZumD_jCBZHTr2Y5oNFb-11" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1440" y="2140" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-2" value="r ^= r &lt;&lt; 13; r ^= r &gt;&gt;&gt; 17; r ^= r &lt;&lt; 5;<br><font color="#007fff">求下次散列值</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1480" y="2320" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-5" value="<font color="#007fff" style="font-size: 10px;">被终止</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1665" y="2260" width="50" height="30" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-8" value="<div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">//通读这个方法的所有代码后可以知道,这个方法主要就是为了扫描工作队列数组获取一个待执行的ForkJoinTask任务</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">//w 是与工作者线程绑定的工作队列,r 是w插入工作队列数组时的随机数种子</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">private ForkJoinTask&lt;?&gt; scan(ForkJoinPool.WorkQueue w, int r) {</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; // m = ws.length-1 工作队列数组的长度是2次幂,m用于通过位运算实现取模运算</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; ForkJoinPool.WorkQueue[] ws; int m;</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; // 可能包含待执行任务的前提条件,这个条件不满足说明整个工作队列数组中都没有待执行的任务,直接返回空</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; if ((ws = workQueues) != null &amp;&amp; (m = ws.length - 1) &gt; 0 &amp;&amp; w != null) {</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; // ss 初始值是w插入工作队列数组的索引, 是一个奇数,插入的第一个w scanState初始值为3</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; int ss = w.scanState;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;"><br></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; // 结合后面 k = (k+1) &amp; m, 用于实现如果ws[k]这个工作队列扫描不到待处理任务就遍历下一个工作队列</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; <font color="#007fff">// origin:遍历工作队列数组的初始索引值</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; // k: 每次循环的索引值</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; // oldSum: 每遍历一圈更新一次,记录上次遍历一圈时的checkSum值</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; // checkSum: 每遍历一圈重置一下,累计某圈遍历中每次循环q.base值(poll指针的值)</font></div><div style="font-size: 9px;"><font style="font-size: 9px;"><b>&nbsp; &nbsp; &nbsp; &nbsp; for (int origin = r &amp; m, k = origin, oldSum = 0, checkSum = 0;;) </b>{</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ForkJoinPool.WorkQueue q; ForkJoinTask&lt;?&gt;[] a; ForkJoinTask&lt;?&gt; t;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int b, n; long c;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <font color="#007fff">&nbsp; //之前创建工作者线程的时候使用上面变量通过类似“开放地址法”的方法求过绑定的工作队列插入到工作队列数组的位置</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //这里其实是取模定位工作队列数组中的一个工作队列,获取的不一定是与当前工作者线程绑定的工作队列</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((q = ws[<b>k</b>]) != null) {</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //q.base是poll指针用于取任务 q.top是push指针用于插入任务, 这里判断q中是否有待执行的任务</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((n = (b = q.base) - q.top) &lt; 0 &amp;&amp;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (a = q.array) != null) {&nbsp; &nbsp; &nbsp;<font color="#007fff"> // 有待执行的任务</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //b取模a.length获取工作队列数组读索引,然后转成内存的相对偏移i</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<b> long i = (((a.length - 1) &amp; b) &lt;&lt; ASHIFT) + ABASE;</b></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //UNSAFE通过偏移量读取这个位置的任务</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((t = ((ForkJoinTask&lt;?&gt;)</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.getObjectVolatile(a, i))) != null &amp;&amp;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; q.base == b) {&nbsp; <font color="#007fff">//q.base是volatile类型,比较一下防止这个任务已经被其他线程读取,其实相当于乐观锁</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //值不等的话说明从上次读取q.base到这次读取q.base之间有其他线程修改了q.base, 这种情况不执行这个任务</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ss &gt;= 0) {&nbsp; <font color="#007fff">//判断与线程绑定的工作队列是否已经激活</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //先将任务从工作队列中移除,再唤醒工作者线程执行</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (U.compareAndSwapObject(a, i, t, null)) {</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; q.base = b + 1;&nbsp; &nbsp;<font color="#007fff">//更新q.base用于下次取临近的下一个任务</font></font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (n &lt; -1)&nbsp; &nbsp; &nbsp; <font color="#007fff">&nbsp;//n是poll push指针的差值,&lt;-1 说明有多个待处理的任务,等于-1即只有一个待处理任务</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;"><b>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //唤醒其他线程帮忙处理其他待执行的任务</b></font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>signalWork</b>(ws, q);</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return t;&nbsp; <font color="#007fff">&nbsp;<b>//当前线程只取q.base处的任务处理</b></font></font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 与线程绑定的工作队列没有激活,上次checkSum为0且当前遍历的工作队列没有激活</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if (oldSum == 0 &amp;&amp;&nbsp; &nbsp;// try to activate</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w.scanState &lt; 0)</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>tryRelease</b>(c = ctl, ws[m &amp; (int)c], AC_UNIT);</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font style="font-size: 9px;"><br></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //下次循环准备</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ss &lt; 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// refresh</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ss = w.scanState;</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //多次移位异或操作,计算下个散列值(称随机值有点不恰当)</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r ^= r &lt;&lt; 1; r ^= r &gt;&gt;&gt; 3; r ^= r &lt;&lt; 10;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; origin = k = r &amp; m;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// move and rescan</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oldSum = checkSum = 0;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //走到这说明当前工作队列中没有待执行任务</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkSum += b;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; <font color="#007fff">&nbsp; &nbsp; //下次循环准备(k = (k + 1) &amp; m)以及循环退出条件</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //如果k位置的工作队列为空则k++,继续循环扫描下一个工作队列,直到工作不为空或者遍历了所有工作队列</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //这里如果相等说明已经遍历了所有工作队列</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((k = (k + 1) &amp; m) == origin) {&nbsp; &nbsp; // continue until stable</font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //遍历所有工作队列后的处理,不一定退出循环</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((ss &gt;= 0 || (ss == (ss = w.scanState))) &amp;&amp;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oldSum == (oldSum = checkSum)) {&nbsp;<font color="#007fff"> &nbsp; //相等说明上一圈和这一圈所有工作队列poll指针都没有移动,即没有读取到可执行任务</font></font></div><div style="font-size: 9px;"><font color="#007fff" style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //绑定的工作队列未激活或被锁定才退出循环</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ss &lt; 0 || w.qlock &lt; 0)&nbsp; &nbsp; // already inactive</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>break</b>;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int ns = ss | INACTIVE;&nbsp; &nbsp; &nbsp; &nbsp;// try to inactivate</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long nc = ((SP_MASK &amp; ns) |</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (UC_MASK &amp; ((c = ctl) - AC_UNIT)));</font></div><div style="font-size: 9px;"><font style="font-size: 9px;"><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>&nbsp; &nbsp; //<br></font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w.stackPred = (int)c;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// hold prev stack top</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.putInt(w, QSCANSTATE, ns);</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (U.compareAndSwapLong(this, CTL, c, nc))</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ss = ns;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w.scanState = ss;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// back out</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkSum = 0;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; }</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">&nbsp; &nbsp; return null;</font></div><div style="font-size: 9px;"><font style="font-size: 9px;">}</font></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=1;" parent="1" vertex="1">
<mxGeometry x="2920" y="1820" width="600" height="940" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-14" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-10" target="NMrCZGO8tHE7oQIJTHmH-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-10" value="<b>scanState</b> &amp;= ~SCANNING;<br><font color="#007fff">SCANNING=1, 即将scanState最后一位置为0(scanState变为偶数),scanState为偶数表示繁忙</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1960" y="2140" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-12" value="WorkQueue" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2020" y="2110" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-17" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-13" target="NMrCZGO8tHE7oQIJTHmH-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-13" target="NMrCZGO8tHE7oQIJTHmH-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-13" value="(<b>currentSteal</b> = <b>task</b>).<b>doExec</b>();<br><font color="#007fff"><b>先执行偷取的任务</b></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1960" y="2220" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-16" target="NMrCZGO8tHE7oQIJTHmH-18" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-23" value="<font color="#007fff" style="font-size: 9px;">3种<br>实现</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="NMrCZGO8tHE7oQIJTHmH-19" vertex="1" connectable="0">
<mxGeometry x="-0.2444" y="-2" relative="1" as="geometry">
<mxPoint y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-16" value="s = status<br>completed = <b>exec</b>();<br>if (completed)&nbsp;<br>s = <b>setCompletion</b>(NORMAL);<br>return s;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="2200" y="2220" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-18" target="froqMD3xnD5BCt7UT14n-24" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-18" value="<div style="">result = compute();</div>&nbsp; return true;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="2440" y="2220" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-20" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ForkJoinTask</b>&lt;V&gt; implements Future&lt;V&gt;, Serializable<br></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;">private static final ExceptionNode[] exceptionTable;</p><p style="margin: 0px 0px 0px 4px;">private static final ReentrantLock exceptionTableLock;</p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;"></span></p><p style="margin: 0px 0px 0px 4px;">private static final ReferenceQueue&lt;Object&gt; exceptionTableRefQueue;</p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;"><br></span></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">volatile int </span><b style="background-color: initial;">status</b><span style="background-color: initial;">; // accessed directly by pool and workers</span><br></p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;">static final int <b>DONE_MASK</b>&nbsp; &nbsp;= 0xf0000000;&nbsp; // mask out non-completion bits</p><p style="margin: 0px 0px 0px 4px;">static final int NORMAL&nbsp; &nbsp; &nbsp; = 0xf0000000;&nbsp; // must be negative</p><p style="margin: 0px 0px 0px 4px;">static final int CANCELLED&nbsp; &nbsp;= 0xc0000000;&nbsp; // must be &lt; NORMAL</p><p style="margin: 0px 0px 0px 4px;">static final int EXCEPTIONAL = 0x80000000;&nbsp; // must be &lt; CANCELLED</p><p style="margin: 0px 0px 0px 4px;">static final int SIGNAL&nbsp; &nbsp; &nbsp; = 0x00010000;&nbsp; // must be &gt;= 1 &lt;&lt; 16</p><p style="margin: 0px 0px 0px 4px;">static final int SMASK&nbsp; &nbsp; &nbsp; &nbsp;= 0x0000ffff;&nbsp; // short bits for tags</p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;">public final ForkJoinTask&lt;V&gt; fork()<br></p><p style="margin: 0px 0px 0px 4px;">public final V join()<br></p><p style="margin: 0px 0px 0px 4px;">public final V invoke()<br></p><p style="margin: 0px 0px 0px 4px;">public static void invokeAll(ForkJoinTask&lt;?&gt; t1, ForkJoinTask&lt;?&gt; t2)<br></p><p style="margin: 0px 0px 0px 4px;">public static void invokeAll(ForkJoinTask&lt;?&gt;... tasks)<br></p><p style="margin: 0px 0px 0px 4px;">public final V get() throws InterruptedException, ExecutionException<br></p><p style="margin: 0px 0px 0px 4px;">......</p><p style="margin: 0px 0px 0px 4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=10;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-480" y="1440.75" width="440" height="279.25" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-21" target="NMrCZGO8tHE7oQIJTHmH-23" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-21" value="U.<b>putOrderedObject</b>(this, QCURRENTSTEAL, null);<br><font style="font-size: 9px;" color="#007fff">将currentSteal设置为null,putOrderedObject这种方式不保证对其他线程立即可见,但相对currentSteal=null 有性能优势</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1960" y="2300" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-28" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-23" target="NMrCZGO8tHE7oQIJTHmH-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-23" target="froqMD3xnD5BCt7UT14n-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-23" value="<b>execLocalTasks</b>();<br><font color="#007fff"><b>再执行本地任务</b><br>读取删除并执行所有本地任务,本地任务即与当前工作者线程绑定的工作队列中的任务</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1960" y="2380" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-25" value="从top指针开始向base指针遍历读取任务并执行<br>U.putOrderedInt(this, QTOP, s);<br>t.doExec();" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2440" y="2380" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-29" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-27" target="NMrCZGO8tHE7oQIJTHmH-25" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-32" value="FILO" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="NMrCZGO8tHE7oQIJTHmH-29" vertex="1" connectable="0">
<mxGeometry x="0.1561" y="-3" relative="1" as="geometry">
<mxPoint x="-5" y="-3" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-31" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="NMrCZGO8tHE7oQIJTHmH-27" target="NMrCZGO8tHE7oQIJTHmH-30" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2390" y="2410" />
<mxPoint x="2390" y="2490" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-33" value="FIFO" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="NMrCZGO8tHE7oQIJTHmH-31" vertex="1" connectable="0">
<mxGeometry x="0.5835" y="-2" relative="1" as="geometry">
<mxPoint x="-1" y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-27" value="队列模式" style="rhombus;whiteSpace=wrap;html=1;rounded=1;" parent="1" vertex="1">
<mxGeometry x="2220.75" y="2380" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="NMrCZGO8tHE7oQIJTHmH-30" value="pollAndExecAll();<br><font color="#007fff">同FILO只不过是从base指针到top指针遍历读取任务并执行</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2440" y="2460" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-1" value="<font color="#007fff" style="font-size: 10px;">总结,主要流程:<br style="font-size: 10px;">扫描工作队列数组偷取待处理任务执行,<br style="font-size: 10px;">偷取的任务执行完毕执行与线程绑定的工作队列中的待处理任务;<br style="font-size: 10px;">如果任务为空则阻塞等待被唤醒</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1080" y="2125" width="310" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-2" target="froqMD3xnD5BCt7UT14n-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-2" value="<div></div>scanState |= SCANNING;<br><font color="#007fff">将scanState重置为SCANNING</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1960" y="2460" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-4" target="froqMD3xnD5BCt7UT14n-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-4" value="<div>if (++nsteals &lt; 0)<span style="background-color: initial;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transferStealCount(pool);</span></div><font color="#007fff">更新与线程绑定的工作队列的偷取任务数量记录 nteals, 溢出后记录到ForkJoinPool.stealCounter上</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1960" y="2540" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-6" value="<div></div><div style="">if (thread != null)</div>thread.afterTopLevelExec();<br><font color="#007fff">留作拓展,方法暂为空</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="1960" y="2620" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-9" value="<div style="font-size: 9px;"><div style="font-size: 9px;"><br></div><div style="font-size: 9px;"><font color="#007fff">先自旋等待因为可能有新的任务提交,自旋完毕</font></div><div style="font-size: 9px;">private boolean <b>awaitWork</b>(WorkQueue w, int r) {</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; // 如果工作队列为空或者正在终止,则返回false</font></div><div style="font-size: 9px;">&nbsp; &nbsp; if (w == null || w.qlock &lt; 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 9px;"><br></div><div style="font-size: 9px;">&nbsp; &nbsp; // w.stackPred: 线程栈,前一个工作队列</div><div style="font-size: 9px;">&nbsp; &nbsp; for (int pred = w.stackPred, spins = SPINS, ss;;) {</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; // 如果工作队列的扫描状态大于等于0,表示有任务需要执行,跳出循环</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; if ((ss = w.scanState) &gt;= 0)</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; // 如果自旋次数大于0,则继续自旋</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; else if (spins &gt; 0) {&nbsp; &nbsp;</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 随机数混淆自旋次数</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r ^= r &lt;&lt; 6;&nbsp;<span style="background-color: initial;">r ^= r &gt;&gt;&gt; 21;&nbsp;</span><span style="background-color: initial;">r ^= r &lt;&lt; 7;</span></div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果自旋次数用尽,随机查找其他工作队列</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (r &gt;= 0 &amp;&amp; --spins == 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WorkQueue v;&nbsp;<span style="background-color: initial;">WorkQueue[] ws;&nbsp;</span><span style="background-color: initial;">int s, j;&nbsp;</span><span style="background-color: initial;">AtomicLong sc;</span></div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果有前驱工作队列,且绑定的线程正在执行任务,则继续自旋</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (pred != 0 &amp;&amp; (ws = workQueues) != null &amp;&amp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (j = pred &amp; SMASK) &lt; ws.length &amp;&amp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (v = ws[j]) != null &amp;&amp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (v.parker == null || v.scanState &gt;= 0))</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spins = SPINS;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; // 如果工作队列已经处于终止状态,则返回false</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; else if (w.qlock &lt; 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 9px;"><br></div><div style=""><font style="font-size: 9px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; // 如果当前线程</font><font style="font-size: 9px;" color="#007fff">自旋次数用尽</font><span style="color: rgb(0, 127, 255); background-color: initial;">未被中断</span></div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; else if (!Thread.interrupted()) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long c, prevctl, parkTime, deadline;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int ac = (int)((c = ctl) &gt;&gt; AC_SHIFT) + (config &amp; SMASK);</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果活跃的工作线程数小于等于0,尝试<b>终止线程池</b></font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((ac &lt;= 0 &amp;&amp; tryTerminate(false, false)) ||</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (runState &amp; STOP) != 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果活跃的工作线程数小于等于0且当前工作队列是最后一个等待任务的队列</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ac &lt;= 0 &amp;&amp; ss == (int)c) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 设置新的控制状态</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prevctl = (UC_MASK &amp; (c + AC_UNIT)) | (SP_MASK &amp; pred);</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int t = (short)(c &gt;&gt;&gt; TC_SHIFT);&nbsp;&nbsp;</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果当前线程数量大于2,则缩小线程池容量</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (t &gt; 2 &amp;&amp; U.compareAndSwapLong(this, CTL, c, prevctl))</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 否则计算等待超时时间</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parkTime = IDLE_TIMEOUT * ((t &gt;= 0) ? 1 : 1 - t);</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prevctl = parkTime = deadline = 0L;</div><div style="font-size: 9px;"><br></div><div style="font-size: 9px;"><font color="#007fff"><span style="white-space: pre;">	</span>&nbsp; &nbsp; //后面代码主要用于让工作者线程进入等待<br></font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread wt = Thread.currentThread();</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 模拟LockSupport的行为</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.putObject(wt, PARKBLOCKER, this);&nbsp; &nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w.parker = wt;</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果工作队列的扫描状态仍然小于0,并且控制状态没有发生变化,则进行等待</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (w.scanState &lt; 0 &amp;&amp; ctl == c)&nbsp; &nbsp; &nbsp;&nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.<b>park</b>(false, parkTime);</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.putOrderedObject(w, QPARKER, null);</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.putObject(wt, PARKBLOCKER, null);</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果工作队列的扫描状态大于等于0,则表示有任务执行,跳出循环</font></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (w.scanState &gt;= 0)</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div style="font-size: 9px;"><span style="background-color: initial;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (parkTime != 0L &amp;&amp; ctl == c &amp;&amp;</span><br></div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deadline - System.nanoTime() &lt;= 0L &amp;&amp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.compareAndSwapLong(this, CTL, c, prevctl))</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 9px;">&nbsp; &nbsp; }</div><div style="font-size: 9px;"><br></div><div style="font-size: 9px;">&nbsp; &nbsp; return true;</div><div style="font-size: 9px;">}</div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=1;" parent="1" vertex="1">
<mxGeometry x="1480" y="2400" width="440" height="840" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-10" value="关键主题:<br style="font-size: 10px;"><ol style=""><li style="">ForkJoinPool任务提交与处理流程?<br><font color="#007fff">关键步骤简述:任务提交到偶数索引的工作队列,然后会唤醒空闲的工作者线程(ctl ID段)执行,如果没有空闲的工作者线程且工作者线程数量未达到上限,就新建工作者线程并注册到工作队列owner字段;<br>工作者线程启动或被唤醒后会扫描工作队列组读取待执行的任务(任务偷取),如果有多个待执行的任务就唤醒其他线程帮忙处理其他待执行任务,处理完偷取的任务,再遍历执行绑定的工作队列中的本地任务,所有任务执行完毕后,自旋扫描工作队列组中的任务,自旋完毕后,进入等待状态等下次被唤醒。</font></li><li style="font-size: 10px;">ForkJoinPool到底会创建多少个工作者线程,多少个工作队列?任务阻塞有什么影响?<br style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">由源码可知每次提交任务,如果空闲线程为0且ctl ADD_WORKER位不为0就可以一直创建工作者线程,由于ctl位32-47记录工作者线程总数且代码中只有溢出时ADD_WORKER位才会变为0,而且TC初始值是-parallelism, 所以理论上最多<b>可以创建parallelism个工作者线程</b>;parallelism最大可以设置为32767。<br>工作队列数量为大于等于并行度的最小2的指数幂的2倍,比如parallelism=8,会创建16个工作队列。<br>像测试中如果提交一批会一直阻塞的任务,如果阻塞任务数量不小于工作者线程数量,会导致所有工作者线程阻塞,之后提交的任务无法被处理。即ForkJoinPool线程也可能被耗尽。<br></font></li><li style="font-size: 10px;">ctl各个位的含义<br><font color="#007fff">见UML图中注释。</font></li><li style="font-size: 10px;">任务窃取的体现<br><font color="#007fff">工作者线程 scan() 会扫描所有工作队列直到找到待执行的任务并执行;ForkJoinTask join() 阶段 helpStealer() 可能窃取窃取者的任务执行。</font></li></ol>" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=top;whiteSpace=wrap;rounded=0;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="680" y="10" width="1420" height="170" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-12" value="<font color="#007fff"><b>任务提交是默认提交到索引为偶数的工作队列</b></font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1390" y="605.75" width="260" height="30" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-13" value="<font color="#007fff"><b>ctl 低32位为0且第47bit不为0,<br>即不存在空闲线程,且工作者线程数量未达到并行度的值<br>就创建工作者线程<br></b></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;shadow=0;" parent="1" vertex="1">
<mxGeometry x="940" y="1119" width="320" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-14" value="ForkJoinTask" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2260" y="2190" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-21" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=0;" parent="1" source="froqMD3xnD5BCt7UT14n-20" target="NMrCZGO8tHE7oQIJTHmH-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-20" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>RecursiveTask&lt;V&gt; (A)</b><br></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">V result;</span><br></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;">protected abstract V compute();<br></p><p style="margin: 0px 0px 0px 4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=10;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-280" y="1760" width="240" height="80" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-22" value="以 RecursiveTask 为例" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2480" y="2190" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-29" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" source="froqMD3xnD5BCt7UT14n-24" target="froqMD3xnD5BCt7UT14n-26" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2760" y="2700" as="targetPoint" />
<Array as="points">
<mxPoint x="2900" y="2250" />
<mxPoint x="2900" y="3260" />
<mxPoint x="740" y="3260" />
<mxPoint x="740" y="3330" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-24" value="Xxx#compute()<br><font color="#007fff">业务类实现compute()方法</font><br><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="2680" y="2220" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-31" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-26" target="froqMD3xnD5BCt7UT14n-30" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-26" value="Xxx#compute()<br><font color="#007fff">业务类实现compute()方法</font><br><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="760" y="3300" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontSize=10;" parent="1" source="KyiJdkHfAW7Gcaq_ivn_-6" target="froqMD3xnD5BCt7UT14n-27" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="380" y="340" as="sourcePoint" />
<mxPoint x="380" y="440" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-27" value="Future&lt;Integer&gt; sum = pool.<b>submit</b>(task);" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="280" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-36" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#dae8fc;strokeColor=#000000;" parent="1" source="froqMD3xnD5BCt7UT14n-30" target="froqMD3xnD5BCt7UT14n-35" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-41" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-30" target="froqMD3xnD5BCt7UT14n-40" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-30" value="<div><div style="text-align: left;">SumTask2 t1 = new SumTask2(low, mid);</div><div style="text-align: left;">SumTask2 t2 = new SumTask2(mid+1, high);</div><div style="text-align: left;">ForkJoinTask&lt;Integer&gt; f1 = t1.<b>fork</b>();</div><div style="text-align: left;">ForkJoinTask&lt;Integer&gt; f2 = t2.<b>fork</b>();</div></div><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1000" y="3300" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-53" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-35" target="froqMD3xnD5BCt7UT14n-52" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-35" value="<div><div style="">return f1.<b>join</b>() + f2.<b>join</b>();<br></div></div><div style=""><font color="#007fff">调用join()方法时说明本线程已经暂时空闲了,会先尝试从工作队列pop等待的任务自己执行,如果任务已经被窃取,还会去窃取者那里偷取任务执行</font></div><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;align=center;" parent="1" vertex="1">
<mxGeometry x="1000" y="3900" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-43" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-40" target="froqMD3xnD5BCt7UT14n-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-44" value="Y" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="froqMD3xnD5BCt7UT14n-43" vertex="1" connectable="0">
<mxGeometry x="-0.0485" y="-4" relative="1" as="geometry">
<mxPoint x="12" y="-4" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-47" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="froqMD3xnD5BCt7UT14n-40" target="froqMD3xnD5BCt7UT14n-45" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1440" y="3330" />
<mxPoint x="1440" y="3410" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-48" value="N" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="froqMD3xnD5BCt7UT14n-47" vertex="1" connectable="0">
<mxGeometry x="0.5636" y="-1" relative="1" as="geometry">
<mxPoint x="11" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-40" value="(t = Thread.currentThread()) <b>instanceof</b> ForkJoinWorkerThread" style="rhombus;whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1260" y="3300" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-50" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-42" target="froqMD3xnD5BCt7UT14n-49" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-42" value="((ForkJoinWorkerThread)t).workQueue<br>.<b>push</b>(this);<br><font color="#007fff">当前线程是ForkJoinWorkerThread就推送到与当前线程<b>绑定的工作队列</b>中</font>" style="whiteSpace=wrap;html=1;fontSize=10;rounded=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1480" y="3300" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-45" value="ForkJoinPool.<b>common</b>.<b>externalPush</b>(this);<br>return this;<br><font color="#007fff">非ForkJoinWorkerThread,就推送到common线程池的偶数索引的工作队列中</font>" style="whiteSpace=wrap;html=1;fontSize=10;rounded=1;" parent="1" vertex="1">
<mxGeometry x="1480" y="3380" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-51" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" source="froqMD3xnD5BCt7UT14n-49" target="KyiJdkHfAW7Gcaq_ivn_-72" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="750" y="1078.1818181818182" as="targetPoint" />
<Array as="points">
<mxPoint x="1940" y="3330" />
<mxPoint x="1940" y="3250" />
<mxPoint x="740" y="3250" />
<mxPoint x="740" y="1085" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-49" value="p.<b>signalWork</b>(p.workQueues, this);<br><font color="#007fff">唤醒其他线程继续<b>扫描并执行</b>工作队列组中的可执行任务</font>" style="whiteSpace=wrap;html=1;fontSize=10;rounded=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1720" y="3300" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-55" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-52" target="froqMD3xnD5BCt7UT14n-54" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-52" target="froqMD3xnD5BCt7UT14n-58" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-52" value="<div><div style=""><div>if ((s = <b>doJoin</b>() &amp;&nbsp;<span style="background-color: initial; font-size: 9px;">DONE_MASK) != <font style="font-size: 9px;">NORMAL</font>)</span></div><div>reportException(s);</div></div></div><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;" parent="1" vertex="1">
<mxGeometry x="1240" y="3900" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-54" value="<div><div style="">return <b>getRawResult</b>();<br></div></div><div style=""><font color="#007fff">读取result字段</font></div><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=center;" parent="1" vertex="1">
<mxGeometry x="1240" y="3980" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-61" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=0;" parent="1" source="froqMD3xnD5BCt7UT14n-56" target="NMrCZGO8tHE7oQIJTHmH-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-56" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>RecursiveAction(A)</b><br></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px;"></p><p style="margin: 0px 0px 0px 4px;">protected abstract void compute();<br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=10;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-560" y="1760" width="240" height="80" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-66" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="froqMD3xnD5BCt7UT14n-58" target="froqMD3xnD5BCt7UT14n-65" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-58" value="<div><div style=""><div>private int doJoin() {</div><div>&nbsp; &nbsp; int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;</div><div>&nbsp; &nbsp; return (s = status) &lt; 0 ?<span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span><font color="#007fff">//任务是否已经完成</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s :&nbsp; <font color="#007fff">//任务已经完成直接返回任务状态</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? <font color="#007fff">//当前线程是否是ForkJoinWorkerThread?&nbsp;</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (w = (wt = (ForkJoinWorkerThread)t).workQueue).<b>tryUnpush</b>(this) <font color="#007fff">//CAS从线程绑定的工作队列top指针处pop当前任务,这时有可能任务被其他线程偷去,导致pop失败</font></div><div><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>&amp;&amp; (s = <b>doExec</b>()) &lt; 0 ? <font color="#007fff">//pop成功直接在当前线程执行任务,然后判断任务是否完成</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wt.pool.<b>awaitJoin</b>(w, this, 0L)&nbsp; <font color="#007fff">//如果任务已被其他线程窃取的处理, 主要就是循环等待任务执行完毕,可能还会帮助Stealer处理任务</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>externalAwaitDone</b>();<span style="white-space: pre;">	</span><font color="#007fff">//非ForkJoinWorkerThread,pop</font></div><div>}</div></div></div><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=3;" parent="1" vertex="1">
<mxGeometry x="1480" y="3830" width="440" height="200" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-60" value="ForkJoinTask" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1295" y="3870" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-62" value="<font color="#007fff">fork本质就是提交子任务</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1025" y="3360" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-69" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="froqMD3xnD5BCt7UT14n-65" target="froqMD3xnD5BCt7UT14n-68" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-73" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="froqMD3xnD5BCt7UT14n-65" target="froqMD3xnD5BCt7UT14n-72" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2350" y="4410" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-65" value="<div><div style=""><div style=""><div style="">final int <b>awaitJoin</b>(WorkQueue w, ForkJoinTask&lt;?&gt; task, long deadline) {</div><div>&nbsp; &nbsp; int s = 0;</div><div>&nbsp; &nbsp; if (task != null &amp;&amp; w != null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ForkJoinTask&lt;?&gt; prevJoin = w.currentJoin;</div><div><font color="#007fff"><span style="white-space: pre;">	</span>//记录当前join的任务到工作队列的currentJoin<br></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; U.<b>putOrderedObject</b>(w, QCURRENTJOIN, task);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; CountedCompleter&lt;?&gt; cc = (task instanceof CountedCompleter) ?</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (CountedCompleter&lt;?&gt;)task : null;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; <b>for (;;)</b> {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((s = task.<b>status</b>) &lt; 0)<span style="white-space: pre;">	</span><font color="#007fff">//任务已经完成直接退出循环</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (cc != null)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>helpComplete</b>(w, cc, 0);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if (<b>w.base == w.top</b> || w.<b>tryRemoveAndExec</b>(task))<font color="#007fff"> //当前ForkJoinWorkerThread线程绑定的工作队列中的<b>本地任务已经执行完毕</b> 或者 成功将任务从队列移除并执行(任务不是已被窃取了么为何还执行这个方法?)</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>helpStealer</b>(w, task);&nbsp;<span style="white-space: pre;">	</span><b><font color="#007fff">//帮助Stealer处理任务</font></b></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((s = task.status) &lt; 0)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long ms, ns;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (deadline == 0L)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ms = 0L;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if ((ns = deadline - System.nanoTime()) &lt;= 0L)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) &lt;= 0L)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ms = 1L;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (<b>tryCompensate</b>(w)) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; task.internalWait(ms);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.<b>getAndAddLong</b>(this, CTL, AC_UNIT); <font color="#007fff">// AC+"1"</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; U.putOrderedObject(w, QCURRENTJOIN, prevJoin);</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; return s;</div><div>}</div></div></div></div><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=1;" parent="1" vertex="1">
<mxGeometry x="1960" y="3710" width="360" height="440" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-67" value="<font color="#007fff">这里可以看到会扫描工作队列组且是从工作队列base指针处窃取任务</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1690" y="2028" width="390" height="30" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-68" value="<div><div style=""><div style=""><div style=""><div><span style="background-color: initial;">private void <b>helpStealer</b>(WorkQueue w, ForkJoinTask&lt;?&gt; task) { <font color="#007fff">//w:当前工作者线程绑定的工作队列,task:join的任务</font></span><br></div><div>&nbsp; &nbsp; WorkQueue[] ws = workQueues; <font color="#007fff">// ws工作队列数组的引用</font></div><div>&nbsp; &nbsp; int oldSum = 0, checkSum, m;</div><div>&nbsp; &nbsp; if (ws != null &amp;&amp; (<b>m</b> = ws.length - 1) &gt;= 0 &amp;&amp; w != null &amp;&amp;&nbsp;<span style="background-color: initial;">task != null) {</span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; do {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkSum = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <font color="#007fff">// 用于稳定性检查</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ForkJoinTask&lt;?&gt; subtask;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WorkQueue j = w, v;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <font color="#007fff">// v 是子任务窃取者</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>descent: for (subtask = task; subtask.status &gt;= 0; )</b> { <font color="#007fff">// 从(j.hint|1)开始遍历奇数工作队列</font></div><div><font color="#007fff"><b><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>//这个循环就是为了遍历工作队列找窃取者</b></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int <b>h = j.hint | 1</b>, k = 0, i; ; k += 2) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (k &gt; m)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<font color="#007fff">// 遍历完了都找不到窃取者</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break descent;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((v = <b>ws[i = (h + k) &amp; m]</b>) != null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (v.currentSteal == subtask) { <font color="#007fff">// 找到了窃取者</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<b> j.hint = i;<span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><font color="#007fff">// hint记录窃取者的工作队列的索引</font></b></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkSum += v.base;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div><b><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><font color="#007fff">//走到这里说明找到了窃取者</font><br></b></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (;;) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ForkJoinTask&lt;?&gt;[] a; int b;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkSum += (b = v.base);<span style="white-space: pre;">	</span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ForkJoinTask&lt;?&gt; <b>next</b> = v.currentJoin;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (subtask.status &lt; 0 || j.currentJoin != subtask ||&nbsp;<span style="background-color: initial;">v.currentSteal != subtask) <font color="#007fff">// 当前线程join的任务已经执行完毕 或 当前线程绑定的工作队列join的任务不是subtask(什么情况下会变?) 或 窃取者的当前偷取的任务不是subtask</font></span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break descent;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (b - v.top &gt;= 0 || (a = v.array) == null) { <font color="#007fff">// 窃取者没有待执行的任务</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((subtask = next) == null)<span style="white-space: pre;">	</span><font color="#007fff">//窃取者join的任务为空</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break descent;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>j = v</b>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<font color="#007fff">// 跳到外层循环</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div><b><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>&nbsp; &nbsp; <font color="#007fff">//获取窃取者base指针处的任务并执行</font><br></b></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = (((a.length - 1) &amp; b) &lt;&lt; ASHIFT) + ABASE;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ForkJoinTask&lt;?&gt; t = ((ForkJoinTask&lt;?&gt;)&nbsp;<span style="background-color: initial;">U.getObjectVolatile(a, i));</span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (v.base == b) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (t == null)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break descent;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (U.compareAndSwapObject(a, i, t, null)) {<span style="white-space: pre;">	</span><font color="#007fff">//将任务从窃取者的工作队列中删除</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v.base = b + 1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ForkJoinTask&lt;?&gt; ps = w.currentSteal;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int top = w.top;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; do {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.<b>putOrderedObject</b>(w, QCURRENTSTEAL, t);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t.<b>doExec</b>();&nbsp; &nbsp; &nbsp; &nbsp; <b><font color="#007fff">// 执行从窃取者那里窃取的任务</font></b></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } while (task.status &gt;= 0 &amp;&amp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w.top != top &amp;&amp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (t = w.pop()) != null);<span style="white-space: pre;">	</span><font color="#007fff">//这里循环是顺便将当前线程绑定的工作队列中的任务执行一下,执行从窃取者那窃取的任务也可能会fork子任务提交到当前线程绑定的工作队列,所以要执行一下</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; U.putOrderedObject(w, QCURRENTSTEAL, ps);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (w.base != w.top)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 不能进一步帮助</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; } while (task.status &gt;= 0 &amp;&amp; oldSum != (oldSum = checkSum)); <font color="#007fff">// join的任务未完成且上次循环有找到窃取者工作队列中待处理的任务就继续循环</font></div><div>&nbsp; &nbsp; }</div><div>}</div></div></div></div></div><div style=""></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=1;" parent="1" vertex="1">
<mxGeometry x="2360" y="3280" width="540" height="770" as="geometry" />
</mxCell>
<mxCell id="froqMD3xnD5BCt7UT14n-72" value="<div><font color="#007fff">//尝试缩减活动线程数量,可能释放或创建一个补偿线程</font></div><div>private boolean <b>tryCompensate</b>(WorkQueue w) {</div><div>&nbsp; &nbsp; boolean canBlock;</div><div>&nbsp; &nbsp; WorkQueue[] ws; long c; int m, pc, sp;</div><div>&nbsp; &nbsp; if (w == null || w.qlock &lt; 0 ||&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// caller terminating</div><div>&nbsp; &nbsp; &nbsp; &nbsp; (ws = workQueues) == null || (m = ws.length - 1) &lt;= 0 ||</div><div>&nbsp; &nbsp; &nbsp; &nbsp; (pc = config &amp; SMASK) == 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// parallelism disabled</div><div>&nbsp; &nbsp; &nbsp; &nbsp; canBlock = false;</div><div>&nbsp; &nbsp; else if ((sp = (int)(c = ctl)) != 0)&nbsp; &nbsp; &nbsp; <font color="#007fff">// 存在空闲的线程,释放空闲的线程</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; canBlock = <b>tryRelease</b>(c, ws[sp &amp; m], 0L);</div><div>&nbsp; &nbsp; else {</div><div><font color="#007fff"><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="white-space: pre;">	</span></span></span>//pc是并行度<br></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; int <b>ac</b> = (int)(c &gt;&gt; AC_SHIFT) + pc;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; int <b>tc</b> = (short)(c &gt;&gt; TC_SHIFT) + pc; <font color="#007fff"><b>//TC段是“-并行度”,再+pc即实际已经创建的工作者线程数量</b></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; int <b>nbusy</b> = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // validate saturation</div><div><font color="#007fff"><span style="white-space: pre;">	</span>//遍历奇数索引的工作队列(即与线程绑定的工作队列),统计处于繁忙状态(即正在执行任务)的工作队列的数量<br></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i &lt;= m; ++i) {&nbsp; &nbsp; &nbsp; &nbsp; // two passes of odd indices</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WorkQueue v;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((v = ws[((i &lt;&lt; 1) | 1) &amp; m]) != null) {<span style="white-space: pre;">	</span><font color="#007fff">//只统计奇数索引的队列,每个统计两次</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((v.scanState &amp; SCANNING) != 0)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++nbusy;<span style="white-space: pre;">	</span><font color="#007fff">//繁忙状态,统计+1</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div><span style="white-space: pre;">	</span><font color="#007fff">//<b>如果 nbusy == tc&lt;&lt;1, 说明所有工作者线程都繁忙</b></font><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (nbusy != (tc &lt;&lt; 1) || ctl != c)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; canBlock = false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// unstable or stale</div><div><font color="#007fff"><span style="white-space: pre;">	</span>//所有工作者线程都繁忙且实际线程数量已经超出并行度限制<br></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; else if (tc &gt;= pc &amp;&amp; ac &gt; 1 &amp;&amp; w.isEmpty()) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long nc = ((AC_MASK &amp; (c - AC_UNIT)) |</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (~AC_MASK &amp; c));&nbsp; &nbsp; &nbsp; &nbsp;// uncompensated, <font color="#007fff">AC段“-1”</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; canBlock = U.compareAndSwapLong(this, CTL, c, nc);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div><font color="#007fff"><span style="white-space: pre;">	</span>//超出最大线程数量</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; else if (tc &gt;= MAX_CAP ||</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (this == common &amp;&amp; tc &gt;= pc + commonMaxSpares))</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new RejectedExecutionException(</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Thread limit exceeded replacing blocked worker");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; else {<span style="white-space: pre;">	</span><font color="#007fff">// similar to tryAddWorker,<b>突破并行度限制继续创建线程</b></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boolean add = false; int rs;&nbsp; &nbsp; &nbsp; // CAS within lock</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long nc = ((AC_MASK &amp; c) |</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (TC_MASK &amp; (c + TC_UNIT)));</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (((rs = lockRunState()) &amp; STOP) == 0)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; add = U.compareAndSwapLong(this, CTL, c, nc);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unlockRunState(rs, rs &amp; ~RSLOCK);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; canBlock = add &amp;&amp; <b>createWorker</b>(); <font color="#007fff">//!!!</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; return canBlock;</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;arcSize=1;align=left;" parent="1" vertex="1">
<mxGeometry x="2360" y="4080" width="360" height="640" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="35guh6oYoebX98XIw8Dt" name="工作队列结构">
<mxGraphModel dx="954" dy="727" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="BbAymJDytvaLM2xfuUxu-1" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="160" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-2" value="..." style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="200" y="240" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-3" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="280" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-4" value="..." style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="520" y="240" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-9" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="600" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-10" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="320" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-24" value="null" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="120" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-31" value="ws" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="80" y="90" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-32" value="null" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="160" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-33" value="null" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="200" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BbAymJDytvaLM2xfuUxu-34" target="BbAymJDytvaLM2xfuUxu-1" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-34" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-35" value="null" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="280" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-36" value="null" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="320" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-37" value="..." style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="520" width="40" height="80" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-38" value="null" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="600" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="BbAymJDytvaLM2xfuUxu-43" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="BbAymJDytvaLM2xfuUxu-42" target="BbAymJDytvaLM2xfuUxu-24" edge="1">