多執行緒 ThreadLocal

2021-10-08 20:58:26 字數 3350 閱讀 7182

目錄

一、threadlocal 概述

1.1 threadlocal 是什麼

1.2、threadlocal 的作用

二、threadlocal 的使用和原始碼分析

2.1 threadlocal 如何使用

2.1.1 常見方法

2.1.2 使用示例

2.2 threadlocal 原始碼分析

2.2.1 set() 方法分析,以及儲存結構

2.2.2 threadlocalmap 分析

2.3 threadlocal 的記憶體洩漏

2.3.1 強引用和弱引用

2.3.2 threadlocal 機制中可能存在的記憶體洩漏情況

2.3.3 若使用執行緒池時,沒有清理 threadlocal

threadlocal 會為每乙個執行緒中都建立乙個副本,每個執行緒僅可訪問自己內部的副本變數,無法互相訪問其他執行緒的副本變數。

本質上是每個執行緒都有乙個 threadlocalmap 型別的變數 threadlocals,以設定的 threadlocal 物件為 key,要儲存的值為 value,儲存到這個 threadlocals 中。

由於每個執行緒都有自己的 threadlocals,故實現了執行緒隔離。且 map 中可以記錄多個值,可以通過 new 新的 threadlocal 物件實現多個值儲存。

set()  儲存值到 threadlocal 中

get()  從 threadlocal 中取值

remove()  從 threadlocal 中取值

public class testthlocal  catch (interruptedexception e) 

system.out.println("刪除前獲取: " + threadlocal.get());

system.out.println("刪除前獲取2: " + threadlocal2.get());

threadlocal.remove();

threadlocal2.remove();

system.out.println("刪除後獲取: " + threadlocal.get());

system.out.println("刪除後獲取2: " + threadlocal2.get());

}).start();

}static class person

}

先檢視 set() 方法的原始碼

public void set(t value)
那麼,看一下 getmap() 的作用,可以看到是獲取當前這個執行緒的變數 threadlocals,這個變數的型別是 threadlocalmap

由此我們可以總結:threadlocal 的原理就是在每乙個執行緒中都有乙個 threadlocalmap 型別的變數 threadlocals,用於儲存threadlocal 設定的值。儲存方式就是,把 threadlocal 物件作為 key 值,要儲存的內容作為 value,儲存有兩個特點:支援多個 threadlocal 儲存,相同的 threadlocal 會被覆蓋

結構圖如下:

由於每個執行緒都是維護自己的 threadlocals 變數,故可以實現執行緒隔離

可以看到儲存值是設定 threadlocalmap 的鍵值對來實現的,

進而檢視 entry 的結構,發現 entry 是乙個弱引用。這就引出了 threadlocal 的記憶體洩漏問題

從 2.2.2 中我們了解到,用來儲存鍵值對的 entry 是乙個弱引用物件。

● 強引用

物件只要有引用,就不會被**

● 弱引用

當沒有強引用來引用這個物件,則gc**器到來時,就會**掉這個弱引用物件

● 執行緒關閉了,但 threadlocal 沒有被**造成記憶體洩漏

在 thread 原始碼中,關閉執行緒會直接將 threadlocals 設為 null,

這是若 threadlocal 是強引用,則只要執行緒不退出,內部儲存的 threadlocal 也不會被**,就變成了記憶體洩漏。

故 jdk 中使用了 弱引用,讓執行緒沒有對 threadlocal 的引用時,threadlocal 物件會被 gc **。

● threadlocal 被**,但是 value 沒**造成記憶體洩漏

從上面可知,當 threadlocal被銷毀後,threadlocal 會被 gc **。但若value中存的也是乙個引用型別且是強引用,則 value 值指向的記憶體空間不會隨著 threadlocal **而**,這就是 threadlocal 造成記憶體洩漏的原因

防止方式:

當 threadlocal 使用完畢後,一定要記得呼叫 remove() 方法!

當使用的是執行緒池,核心執行緒不會被退出,若沒有清理 threadlocal,則會導致下次使用,會訪問到上次使用時存下來的值。且若是重複使用,可能造成 threadlocalmap 儲存越來越多的無用內容,造成記憶體占用

多執行緒 ThreadLocal

執行緒的變數副本 就像命名一樣 每個執行緒隔離。每個thread都有自己的threadlocalmap,threadlocalmap的底層是使用陣列 其中每個entry,它的key是threadlocal k,繼承自weakreference,也就是我們常說的弱引用型別,可以簡單地將它的key視作t...

Java多執行緒 ThreadLocal

threadlocal 是jdk 包提供的,它提供了執行緒本地變數,也就是如果你建立了乙個threadlocal 變數,那麼訪問這個變數的每個執行緒都會有這個變數的乙個本地副本。當多個執行緒操作這個變數時,實際操作的是自己本地記憶體裡面的變數,從而避免了執行緒安全問題。建立乙個threadlocal...

多執行緒筆記 ThreadLocal

執行緒本地變數 set 設定到當前執行緒內的map中 所以不能被執行緒共享 threadlocal應用 spring 宣告式事務 threadlocal可以保證 乙個執行緒儲存同乙個物件 所以資料庫連線就可以存在threadlocal內乙個事務必須在乙個連線內,spring 宣告事務就是使用thre...