Quelle est la raison pour laquelle ThreadLocal provoque un MOO mémoire ?
La couche inférieure de ThreadLocal stocke les données via ThreadLocalMap
Le code source est le suivant :
Lorsque nous utilisons ThreadLocal.set(), la valeur et la clé de l'ensemble (c'est-à-dire, la classe ThreadLocal définie par l'entreprise elle-même) sera stockée dans Le code source
dans le tableau Entry[] de ThreadLocalMap est le suivant :
où Entry implémente une référence faible WeakReference, et la clé d'entrée (c'est-à-dire la classe ThreadLocal définie par l'entreprise) sera regroupée dans une référence faible et est utilisée comme clé d'entrée. La définition de la référence faible de Java est que lorsque la JVM effectue une analyse de récupération de place et trouve un objet avec uniquement des références faibles, elle recyclera immédiatement l'objet. C'est un moyen d'éviter un débordement de mémoire lorsque ThreadLocal a été conçu à l'origine
. Le code source est le suivant :
Bien que la clé soit conditionnée dans une référence faible et sera recyclée par le mécanisme de récupération de place, la valeur peut avoir une chaîne de référence forte lorsque le thread (Thread) ne meurt pas.
En raison de value
est une référence forte. Tant que Thread
ne meurt pas, comme un pool de threads, cette chaîne de référence forte existera, alors value.
ne sera pas recyclé, provoquant éventuellement un débordement de mémoirevalue
是强引用,只要 Thread
不死亡时,例如线程池,这条强引用链就会存在,那么value
就不会回收,可能造成内存溢出
引用关系如下: Thread ==> ThreadLocalMap ==> Entry ==> value
但是这个消除强引用链的动作是需要业务方在get的情况下触发的,可能业务方并不会get、也可能get是key不为空,并不会触发 expungeStaleEntry 类。所以开发者要养成良好的习惯,记得用完 ThreadLocal
时,调一次ThreadLocal.remove()
方法或者 ThreadLocal.set(null)
ThreadLocal.remove()
ou ThreadLocal.set(null)
lorsqu'ils ont fini d'utiliser ThreadLocal code> code><p><strong>Utilisation correcte</strong><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">public class ThreadLocalTest {
/**
* 未初始化的本地线程变量
*/
private static ThreadLocal<User> userThreadLocal = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
int threadNum = 10;
List<Thread> threadList = Lists.newArrayList();
for (int i = 0; i < threadNum; ++i) {
long userId = i;
Thread t = new Thread(() -> {
try {
// 设置变量值
userThreadLocal.set(new User(userId, "lanxing" + userId, "2x"));
// 使用变量
doSomething();
} finally {
// 移除变量
userThreadLocal.remove(); //移除ThreadLocal变量
}
}, "T" + i);
threadList.add(t);
t.start();
}
for (int i = 0; i < threadNum; ++i) {
threadList.get(i).join();
}
}
private static void doSomething() {
log.info("Use ThreadLocal variable :{}", JSON.toJSONString(userThreadLocal.get()));
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private Long id;
private String name;
private String level;
}</pre><div class="contentsignin">Copier après la connexion</div></div></p>
<blockquote>Résultat d'impression :<p><br><br><br>14:30:26.790 [T2] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":2," level":"2x","name":"lanxing2"}<br>14:30:26.789 [T5] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":5,"level": "2x", "name": "lanxing5"}<br>14: 30: 26.792 [T0] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal : {"id": 0, "level": "2x" ,"name": "lanxing0"}<br>14:30:26.792 [T4] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":4,"level":"2x","name ":"lanxing4"}<br>14:30:26.792 [T8] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":8,"level":"2x","name":" lanxing8"}<br>14:30:26.791 [T1] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":1,"level":"2x","name":"lanxing1"} <br>14:30:26.792 [T7] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":7,"level":"2x","name":"lanxing7"}</p>14 : 30:26.792 [T6] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":6,"level":"2x","name":"lanxing6"}</blockquote>14:30:26.791 [T9] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":9,"level":"2x","name":"lanxing9"}🎜14:30:26.790 [T3] INFO io.zhengsh.order.tool.ThreadLocalTest - Utiliser la variable ThreadLocal :{"id":3,"level":"2x","name":"lanxing3"}🎜🎜
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!