-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathThreadLocal.drawio
More file actions
257 lines (257 loc) · 42.4 KB
/
Copy pathThreadLocal.drawio
File metadata and controls
257 lines (257 loc) · 42.4 KB
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
<mxfile host="Electron" modified="2024-04-22T13:50:09.598Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.6.5 Chrome/114.0.5735.243 Electron/25.3.1 Safari/537.36" etag="a0qBBFDz10tYFLxJC-TS" version="21.6.5" type="device">
<diagram id="h3seWhRiCq7StGXtS9yJ" name="第 1 页">
<mxGraphModel dx="2950" dy="804" 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="l43vFdsVM3XjgTu8qxaD-1" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="40" y="920" width="200" height="140" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-2" value="TLHolder.java" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="95" y="900" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-3" value="ThreadLocal&lt;Integer&gt; tc1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="60" y="940" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-4" value="ThreadLocal&lt;Integer&gt; tc2" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="60" y="1000" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-5" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="40" y="1100" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-6" value="TLHolder2.java" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="90" y="1080" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-7" value="ThreadLocal&lt;Integer&gt; tc3" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="60" y="1120" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-10" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="361.25" y="860" width="160" height="200" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-11" value="Thread 1" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="410" y="840" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-18" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="371.25" y="890" width="140" height="160" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-19" value="<font style="font-size: 10px"><span>ThreadLocalMap&nbsp;</span>threadLocals</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="366.25" y="870" width="150" height="20" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-13" value="referent=tc1<br>value=v11" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="388.75" y="910" width="102.5" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-20" value="<div>referent=tc2</div><div>value=v12</div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="388.75" y="950" width="102.5" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-21" value="<div>referent=tc3</div><div>value=v13</div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="388.75" y="990" width="102.5" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-22" style="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="l43vFdsVM3XjgTu8qxaD-3" target="l43vFdsVM3XjgTu8qxaD-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-38" value="<font style="font-size: 8px">threadLocalHashCode1</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontColor=#007FFF;" parent="l43vFdsVM3XjgTu8qxaD-22" vertex="1" connectable="0">
<mxGeometry x="-0.1912" relative="1" as="geometry">
<mxPoint x="12" y="-8" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-23" value="<span style="font-size: 8px"><font color="#b9e0a5">threadLocalHashCode2</font></span>" style="edgeStyle=none;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=#d5e8d4;strokeColor=#82b366;" parent="1" source="l43vFdsVM3XjgTu8qxaD-4" target="l43vFdsVM3XjgTu8qxaD-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-24" value="<font style="font-size: 8px" color="#ffd966">threadLocalHashCode3</font>" style="edgeStyle=none;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=#fff2cc;strokeColor=#d6b656;" parent="1" source="l43vFdsVM3XjgTu8qxaD-7" target="l43vFdsVM3XjgTu8qxaD-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-25" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="360" y="1100" width="160" height="200" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-26" value="Thread 2" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="408.75" y="1080" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-27" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="370" y="1130" width="140" height="160" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-29" value="<div>referent=tc1</div><div>value=v21</div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="387.5" y="1150" width="102.5" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-30" value="<div>referent=tc2</div><div>value=v22</div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="387.5" y="1190" width="102.5" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-31" value="<div>referent=tc3</div><div>value=v23</div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="387.5" y="1230" width="102.5" height="40" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-32" style="edgeStyle=none;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="l43vFdsVM3XjgTu8qxaD-3" target="l43vFdsVM3XjgTu8qxaD-29" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-39" value="threadLocalHashCode1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=8;fontColor=#007FFF;" parent="l43vFdsVM3XjgTu8qxaD-32" vertex="1" connectable="0">
<mxGeometry x="-0.0901" y="4" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-33" value="<span style="font-size: 8px"><font color="#b9e0a5">threadLocalHashCode2</font></span>" style="edgeStyle=none;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=#d5e8d4;strokeColor=#82b366;" parent="1" source="l43vFdsVM3XjgTu8qxaD-4" target="l43vFdsVM3XjgTu8qxaD-30" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-34" value="<span style="font-size: 8px"><font color="#ffd966">threadLocalHashCode3</font></span>" style="edgeStyle=none;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=#fff2cc;strokeColor=#d6b656;" parent="1" source="l43vFdsVM3XjgTu8qxaD-7" target="l43vFdsVM3XjgTu8qxaD-31" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-35" value="<font style="font-size: 10px">Entry</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="421.25" y="890" width="40" height="20" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-36" value="<font style="font-size: 10px"><span>ThreadLocalMap&nbsp;</span>threadLocals</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="363.75" y="1110" width="150" height="20" as="geometry" />
</mxCell>
<mxCell id="l43vFdsVM3XjgTu8qxaD-37" value="<font style="font-size: 10px">Entry</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="418.75" y="1130" width="40" height="20" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-25" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;endArrow=open;endFill=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-2" target="OFWOy6sgKmJJG_9dfcx7-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-2" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>TLHolder</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">测试类</font></p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;">private static final ThreadLocal&lt;Integer&gt; <b>tc</b> = ThreadLocal.withInitial(</p><p style="margin: 0px 0px 0px 4px;"><span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>() -&gt; 0);<br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;">public static int incrementAndGet();</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="-400" y="80" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-15" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-4" target="OFWOy6sgKmJJG_9dfcx7-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-49" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-4" target="OFWOy6sgKmJJG_9dfcx7-48">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-4" value="TLHolder.incrementAndGet()<br><font color="#007fff">线程每完成一个任务执行一下</font>" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="40" y="240" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-5" value="<font style="font-size: 16px;">ThreadLocal 实现原理<br></font><font style="font-size: 12px;"><br>测试DEMO演示了一个借助ThreadLocal统计线程池各个核心线程完成任务的数量。</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="40" y="10" width="460" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-6" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">ThreadLocal&lt;T&gt;</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff">//用于计算ThreadLocalMap索引</font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final int <b>threadLocalHashCode</b> = nextHashCode();</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static AtomicInteger <b>nextHashCode</b> = new AtomicInteger();</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final int HASH_INCREMENT = 0x61c88647;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="-800" y="80" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-10" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-7" target="OFWOy6sgKmJJG_9dfcx7-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-13" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-7" target="OFWOy6sgKmJJG_9dfcx7-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-7" value="tc = ThreadLocal.withInitial(() -&gt; 0);<br><font color="#007fff">创建带初始化值初始化方法的ThreadLocal对象</font>" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="40" y="160" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-9" value="return new SuppliedThreadLocal&lt;&gt;(supplier);" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="280" y="160" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-12" 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;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-11" target="OFWOy6sgKmJJG_9dfcx7-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-11" value="<div style="text-align: center;"><b>SuppliedThreadLocal</b><b style="background-color: initial;">&lt;T&gt;</b></div><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//只是拓展一个函数式初始值初始化方法</font></p><p style="margin: 0px 0px 0px 4px;">private final Supplier&lt;? extends T&gt; supplier;<br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected T initialValue()</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="-800" y="240" width="360" height="80" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-17" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-14" target="OFWOy6sgKmJJG_9dfcx7-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-23" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-14" target="OFWOy6sgKmJJG_9dfcx7-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-14" value="int count = tc.<b>get</b>() + 1;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="280" y="240" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-21" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-16" target="OFWOy6sgKmJJG_9dfcx7-20">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-39" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-16" target="OFWOy6sgKmJJG_9dfcx7-40">
<mxGeometry relative="1" as="geometry">
<mxPoint x="521.25" y="515" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-16" value="tc.<b>set</b>(count);" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="280" y="500" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-20" value="return count;" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="280" y="585" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-32" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-22" target="OFWOy6sgKmJJG_9dfcx7-31">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-22" value="<div style="font-size: 11px;">Thread t = Thread.currentThread();</div><div style="font-size: 11px;">ThreadLocalMap map = <b>getMap</b>(t);</div><div style="font-size: 11px;">if (map != null) {</div><div style="font-size: 11px;"><font color="#007fff">&nbsp; &nbsp; //this 是 ThreadLocal 对象</font></div><div style="font-size: 11px;">&nbsp; &nbsp; ThreadLocalMap.Entry e = map.<b>getEntry</b>(this);</div><div style="font-size: 11px;">&nbsp; &nbsp; if (e != null) {</div><div style="font-size: 11px;"><span style="background-color: initial;">&nbsp; &nbsp; &nbsp; &nbsp; T result = (T)e.value;</span><br></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; return result;</div><div style="font-size: 11px;">&nbsp; &nbsp; }</div><div style="font-size: 11px;">}</div><div style="font-size: 11px;"><font color="#007fff">// e == null, 就调用上面函数式方法设置初始值</font></div><div style="font-size: 11px;">return setInitialValue();</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=4;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="521.25" y="190" width="280" height="160" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-27" style="rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=-0.003;exitY=0.588;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-24" target="OFWOy6sgKmJJG_9dfcx7-26">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-24" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>Thread</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">private volatile String name;</span><br></p><p style="margin: 0px 0px 0px 4px;">private int&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; priority;</p><p style="margin: 0px 0px 0px 4px;">private Thread&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;threadQ;</p><p style="margin: 0px 0px 0px 4px;">private long&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;eetop;</p><p style="margin: 0px 0px 0px 4px;">private boolean&nbsp; &nbsp; &nbsp;single_step;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//是否是守护线程</font></p><p style="margin: 0px 0px 0px 4px;">private boolean&nbsp; &nbsp; &nbsp;daemon = false;</p><p style="margin: 0px 0px 0px 4px;">private boolean&nbsp; &nbsp; &nbsp;stillborn = false;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//线程任务</font></p><p style="margin: 0px 0px 0px 4px;">private Runnable target;</p><p style="margin: 0px 0px 0px 4px;">private ThreadGroup group;</p><p style="margin: 0px 0px 0px 4px;">private ClassLoader contextClassLoader;</p><p style="margin: 0px 0px 0px 4px;">private AccessControlContext inheritedAccessControlContext;</p><p style="margin: 0px 0px 0px 4px;">private static int threadInitNumber;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//线程本地变量的Map</font></p><p style="margin: 0px 0px 0px 4px;">ThreadLocal.ThreadLocalMap <b>threadLocals</b> = null;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//可继承的线程本地变量的Map</font></p><p style="margin: 0px 0px 0px 4px;">ThreadLocal.ThreadLocalMap <b>inheritableThreadLocals</b> = null;</p><p style="margin: 0px 0px 0px 4px;">private long stackSize;</p><p style="margin: 0px 0px 0px 4px;">private long nativeParkEventPointer;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//Thread ID</font></p><p style="margin: 0px 0px 0px 4px;">private long tid;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//用于生成Thread ID&nbsp;</font></p><p style="margin: 0px 0px 0px 4px;">private static long threadSeqNumber;</p><p style="margin: 0px 0px 0px 4px;">private volatile int threadStatus = 0;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;">ThreadLocalMap getMap(Thread t)</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="-400" y="240" width="360" height="400" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-30" style="rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-26" target="OFWOy6sgKmJJG_9dfcx7-28">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-26" value="<div style="text-align: center;"><b>ThreadLocalMap</b></div><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;"><font color="#007fff">//ThreadLocalMap初始容量</font></span></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">private static final int INITIAL_CAPACITY = 16;</span><br></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;"><font color="#007fff">//哈希表</font></span></p><p style="margin: 0px 0px 0px 4px;">private Entry[] <b>table</b>;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//实际元素个数</font></p><p style="margin: 0px 0px 0px 4px;">private int <b>size</b> = 0;</p><p style="margin: 0px 0px 0px 4px;">private int threshold;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="-800" y="360" width="360" height="160" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-28" value="<div style="text-align: center;"><b>Entry </b>extends&nbsp;<span style="background-color: initial;">WeakReference&lt;ThreadLocal&lt;?&gt;&gt;</span></div><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;"><font color="#007fff"><b>//KEY是 ThreadLocal&lt;?&gt; 的弱引用类型</b></font></span></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;"><font color="#007fff"><br></font></span></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;"><font color="#007fff">//VALUE</font></span></p><p style="margin: 0px 0px 0px 4px;">Object value;<br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="-1200" y="360" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-34" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-31" target="OFWOy6sgKmJJG_9dfcx7-33">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-31" value="<div style="font-size: 11px;"><div>int i = key.<b>threadLocalHashCode</b> &amp; (table.length - 1);</div><div>Entry e = table[i];</div><div>if (e != null &amp;&amp; e.get() == key)</div><div>&nbsp; &nbsp; return e;</div><div>else</div><div><font color="#007fff">&nbsp; &nbsp; //e == null 或者 哈希冲突</font></div><div>&nbsp; &nbsp; return <b>getEntryAfterMiss</b>(key, i, e);</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=4;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="840" y="220" width="280" height="100" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-36" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-33" target="OFWOy6sgKmJJG_9dfcx7-35">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-33" value="<div style="">getEntryAfterMiss(key, i, e);<br></div>" style="rounded=1;whiteSpace=wrap;html=1;align=center;arcSize=15;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="1160" y="240" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-35" value="<div style=""><div>Entry[] tab = table;</div><div>int len = tab.length;</div><div><br></div><div>while (e != null) {</div><div>&nbsp; &nbsp; ThreadLocal&lt;?&gt; k = e.get();</div><div>&nbsp; &nbsp; if (k == key)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return e;</div><div>&nbsp; &nbsp; if (k == null) <font color="#007fff">//Entry中key是弱引用,可能被GC导致为null,此时说明Entry对象已经过期,需要删除</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; <b>expungeStaleEntry</b>(i); <font color="#007fff">//这个方法就是删除过期Entry, 对于线性探测算法就是</font><font color="#007fff">后面的元素往前移,把刚空出的位置再填上</font></div><div>&nbsp; &nbsp; else <font color="#007fff">//哈希冲突</font></div><div><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; //深入内部实现可以看到用的是开放定址法的线性探测再哈希</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; i = <b>nextIndex</b>(i, len);</div><div>&nbsp; &nbsp; e = tab[i];</div><div>}</div><div>return null;</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=3;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="1400" y="160" width="320" height="220" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-37" value="总结:<br><ol><li>ThreadLocal 本身用于计算哈希索引以及作为读写值的门面,本身不存储数据,数据存储在线程的 ThreadLocalMap 成员;&nbsp;</li><li>ThreadLocalMap 以 ThreadLocal&lt;?&gt;&gt; 弱引用类型作为 KEY,当ThreadLocal 对象强引用不存在后,下次GC KEY会变为 null, 意味着Entry过期,会在下次索引时清除(get set 等操作内部都会检查过期的KEY(包括其他ThreadLocal设置的过期的KEY),并进行清理);</li><li>ThreadLocalMap 采用开放定址法的<b>线性探测再散列算法</b>解决哈希冲突。</li><li>ThreadLocal 内存泄露问题 (以不手动清理的前提下讨论ThreadLocal为何会内存泄露)<br>这里的内存泄露是指不调用 remove(), ThreadLocalMap Entry 会内存泄露(包括Key Value),每次使用完后都调用remove()清理是没有内存泄露问题的,(都已经清了还怎么泄露)详细在Markdown中解析。<br></li></ol>" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=top;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="560" y="10" width="680" height="170" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-40" target="OFWOy6sgKmJJG_9dfcx7-43">
<mxGeometry relative="1" as="geometry">
<mxPoint x="840" y="530" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-45" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-40" target="OFWOy6sgKmJJG_9dfcx7-44">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-40" value="<div style=""><div style="">Thread t = Thread.currentThread();</div><div style="">ThreadLocalMap map = getMap(t);</div><div style="">if (map != null) {</div><div style="">&nbsp; &nbsp; map.set(this, value);</div><div style="">} else {</div><div style="">&nbsp; &nbsp; createMap(t, value);</div><div style="">}</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=4;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="521.25" y="475" width="280" height="110" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-43" target="OFWOy6sgKmJJG_9dfcx7-46">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-43" value="<div style="">map.set(this, value);<br></div>" style="rounded=1;whiteSpace=wrap;html=1;align=center;arcSize=15;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="840" y="460" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-44" value="<div style="">createMap(t, value);<br></div><div style=""><font color="#007fff">创建Map并设置值,比较简单不细讲了</font></div>" style="rounded=1;whiteSpace=wrap;html=1;align=center;arcSize=15;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="840" y="540" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-46" value="<div style=""><div>Entry[] tab = table;</div><div>int len = tab.length;</div><div>int i = key.threadLocalHashCode &amp; (len-1);</div><div><font color="#007fff">//这个for循环处理值更新、哈希冲突</font></div><div>for (Entry e = tab[i];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; e != null;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; e = tab[i = nextIndex(i, len)]) {<font color="#007fff"> //冲突,线性探测再散列</font></div><div>&nbsp; &nbsp; ThreadLocal&lt;?&gt; k = e.get();</div><div><br></div><div>&nbsp; &nbsp; if (k == key) { /<font color="#007fff">/更新值</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; e.value = value;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return;</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; if (k == null) { <font color="#007fff">//key已经过期</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; <b>replaceStaleEntry</b>(key, value, i);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return;</div><div>&nbsp; &nbsp; }</div><div>}</div><div><font color="#007fff">//值不存在</font></div><div>tab[i] = new Entry(key, value);</div><div>int sz = ++size;</div><div>if (!<b>cleanSomeSlots</b>(i, sz) &amp;&amp; sz &gt;= threshold)</div><div>&nbsp; &nbsp; rehash();</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=2;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="1160" y="400" width="320" height="320" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-51" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-48" target="OFWOy6sgKmJJG_9dfcx7-50">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-48" value="TLHolder.remove()<br><font color="#007fff">用完之后必须手动清理下</font>" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="40" y="710" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-53" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-50" target="OFWOy6sgKmJJG_9dfcx7-54">
<mxGeometry relative="1" as="geometry">
<mxPoint x="560.0000000000005" y="740" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-50" value="tc.<b>remove</b>();" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="280" y="710" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-56" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="OFWOy6sgKmJJG_9dfcx7-54" target="OFWOy6sgKmJJG_9dfcx7-55">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-54" value="<div style=""><div style=""><div>ThreadLocalMap m = getMap(Thread.currentThread());</div><div>if (m != null) {</div><div>&nbsp; &nbsp; m.<b>remove</b>(this);</div><div>}</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=14;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="520" y="710" width="280" height="60" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-55" value="<div style=""><div style=""><div>Entry[] tab = table;</div><div>int len = tab.length;</div><div>int i = key.threadLocalHashCode &amp; (len-1);</div><div>for (Entry e = tab[i];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; e != null;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; e = tab[i = nextIndex(i, len)]) {<font color="#007fff" style="font-size: 10px;">//线性探测寻址</font></div><div>&nbsp; &nbsp; if (e.get() == key) {<font color="#007fff"> //e.get()获取的是软引用内部的referent</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; e.<b>clear</b>(); <font color="#007fff">//将 referent 设置为 null</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; <b>expungeStaleEntry</b>(i);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return;</div><div>&nbsp; &nbsp; }</div><div>}</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=4;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="840" y="650" width="240" height="180" as="geometry" />
</mxCell>
<mxCell id="OFWOy6sgKmJJG_9dfcx7-57" value="<font color="#007fff">不同线程操作同一个ThreadLocal对象,<br>实际操作的是是不同的ThreadLocalMap</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="40" y="840" width="230" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>