多執行緒 ThreadLocal原理(二)

2021-09-24 18:40:33 字數 2943 閱讀 5720

一、用法

threadlocal用於儲存某個執行緒共享變數:對於同乙個static threadlocal,不同執行緒只能從中get,set,remove自己的變數,而不會影響其他執行緒的變數。

1、threadlocal.get: 獲取threadlocal中當前執行緒共享變數的值。

2、threadlocal.set: 設定threadlocal中當前執行緒共享變數的值。

3、threadlocal.remove: 移除threadlocal中當前執行緒共享變數的值。

4、threadlocal.initialvalue: threadlocal沒有被當前執行緒賦值時或當前執行緒剛呼叫remove方法後呼叫get方法,返回此方法值。

package com.coshaho.reflect;

/*** threadlocal用法

* @author coshaho

* */

public class mythreadlocal

};public static void main(string args)

public static class myintegertask implements runnable

@override

public void run()else

}trycatch (interruptedexception e)

} }

}public static class mystringtask implements runnable

@override

public void run() else

trycatch (interruptedexception e)}}

}}

執行結果如下:

呼叫get方法時,當前執行緒共享變數沒有設定,呼叫initialvalue獲取預設值!

執行緒integertask1: 0

呼叫get方法時,當前執行緒共享變數沒有設定,呼叫initialvalue獲取預設值!

執行緒integertask2: 0

呼叫get方法時,當前執行緒共享變數沒有設定,呼叫initialvalue獲取預設值!

呼叫get方法時,當前執行緒共享變數沒有設定,呼叫initialvalue獲取預設值!

執行緒stringtask1: a

執行緒stringtask2: a

執行緒stringtask1: aa

執行緒stringtask2: aa

執行緒integertask1: 1

執行緒integertask2: 1

執行緒stringtask1: aaa

執行緒stringtask2: aaa

執行緒integertask2: 2

執行緒integertask1: 2

執行緒stringtask2: aaaa

執行緒stringtask1: aaaa

執行緒integertask2: 3

執行緒integertask1: 3

執行緒stringtask1: aaaaa

執行緒stringtask2: aaaaa

呼叫get方法時,當前執行緒共享變數沒有設定,呼叫initialvalue獲取預設值!

執行緒integertask2: 0

呼叫get方法時,當前執行緒共享變數沒有設定,呼叫initialvalue獲取預設值!

執行緒integertask1: 0

二、原理

執行緒共享變數快取如下:

thread.threadlocalmap<threadlocal,object>;

1、thread: 當前執行緒,可以通過thread.currentthread()獲取。

2、threadlocal:我們的staticthreadlocal變數。

3、object: 當前執行緒共享變數。

我們呼叫threadlocal.get方法時,實際上是從當前執行緒中獲取threadlocalmap<threadlocal,object>,然後根據當前threadlocal獲取當前執行緒共享變數object。

threadlocal.set,threadlocal.remove實際上是同樣的道理。

這種儲存結構的好處:

1、執行緒死去的時候,執行緒共享變數threadlocalmap則銷毀。

2、threadlocalmap鍵值對數量為threadlocal的數量,一般來說threadlocal數量很少,相比在threadlocal中用map鍵值對儲存執行緒共享變數(thread數量一般來說比threadlocal數量多),效能提高很多。

關於threadlocalmap<threadlocal,object>弱引用問題:

當執行緒沒有結束,但是threadlocal已經被**,則可能導致執行緒中存在threadlocalmap<null,object>的鍵值對,造成記憶體洩露。(threadlocal被**,threadlocal關聯的執行緒共享變數還存在)。

雖然threadlocal的get,set方法可以清除threadlocalmap中key為null的value,但是get,set方法在記憶體洩露後並不會必然呼叫,所以為了防止此類情況的出現,我們有兩種手段。

1、使用完執行緒共享變數後,顯示呼叫threadlocalmap.remove方法清除執行緒共享變數;

2、jdk建議threadlocal定義為private static,這樣threadlocal的弱引用問題則不存在了。

多執行緒 ThreadLocal

目錄 一 threadlocal 概述 1.1 threadlocal 是什麼 1.2 threadlocal 的作用 二 threadlocal 的使用和原始碼分析 2.1 threadlocal 如何使用 2.1.1 常見方法 2.1.2 使用示例 2.2 threadlocal 原始碼分析 2...

多執行緒 ThreadLocal

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

Java多執行緒 ThreadLocal

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