面試再問ThreadLocal,別說你不會

2022-09-13 04:24:18 字數 3214 閱讀 6555

尊重原創,傳送門:

以前面試的時候問到threadlocal總是一臉懵逼,只知道有這個哥們,不了解他是用來做什麼的,更不清楚他的原理了。表面上看他是和多執行緒,執行緒同步有關的乙個工具類,但其實他與執行緒同步機制無關。執行緒同步機制是多個執行緒共享同乙個變數,而threadlocal是為每個執行緒建立乙個單獨的變數副本,每個執行緒都可以改變自己的變數副本而不影響其它執行緒所對應的副本。官方api上是這樣介紹的:該類提供了執行緒區域性(thread-local)變數。這些變數不同於它們的普通對應物,因為訪問某個變數(通過其 get 或 set 方法)的每個執行緒都有自己的區域性變數,它獨立於變數的初始化副本。threadlocal例項通常是類中的 private static 字段,它們希望將狀態與某乙個執行緒(例如,使用者 id 或事務 id)相關聯。

threadlocal定義了四個方法:

public

class

seqcount};

public

intnextseq()

public

static

void

main

(string [

] args)

public

static

class

seqthread

extends

thread

@override

public

void

run()}

}}

執行結果:

}執行結果:

threadlocalmap內部是利用entry來進行key-value的儲存的。

static

class

entry

extends

weakreference

?>>

}

上面原始碼中key就是threadlocal,value就是值,entry繼承weakreference,所以entry對應key的引用(threadlocal例項)是乙個弱引用。

/**

* set the value associated with key.

** @param key the thread local object

* @param value the value to be set

*/private

void

set(threadlocal<

?> key, object value)

// key == null,但是存在值(因為此處的e != null),說明之前的threadlocal物件已經被**了

if(k == null)

}//threadlocal對應的key例項不存在,new乙個

tab[i]

=new

entry

(key, value)

;int sz =

++size;

//清楚陳舊的entry(key == null的)

// 如果沒有清理陳舊的 entry 並且陣列中的元素大於了閾值,則進行 rehashif(

!cleansomeslots

(i, sz)

&& sz >= threshold)

rehash()

;}

這個set操作和集合map解決雜湊衝突的方法不同,集合map採用的是鏈位址法,這裡採用的是開放定址法(線性探測)。set()方法中的replacestaleentry()和cleansomeslots(),這兩個方法可以清除掉key ==null的例項,防止記憶體洩漏。

private entry getentry

(threadlocal<

?> key)

由於採用了開放定址法,當前keu的雜湊值和元素在陣列中的索引並不是一一對應的,首先取乙個猜測數(key的雜湊值),如果所對應的key是我們要找的元素,那麼直接返回,否則呼叫getentryaftermiss

private entry getentryaftermiss

(threadlocal<

?> key,

int i, entry e)

return null;

}

這裡一直在探測尋找下乙個元素,知道找的元素的key是我們要找的。這裡當key==null時,呼叫expungestaleentry有利於gc的**,用於防止記憶體洩漏。

threadlocalmap的key為threadlocal例項,他是乙個弱引用,我們知道弱引用有利於gc的**,當key == null時,gc就會**這部分空間,但value不一定能被**,因為他和current thread之間還存在乙個強引用的關係。由於這個強引用的關係,會導致value無法**,如果執行緒物件不消除這個強引用的關係,就可能會出現oom。有些時候,我們呼叫threadlocalmap的remove()方法進行顯式處理。

threadlocal不是用來解決共享變數的問題,也不是協調執行緒同步,他是為了方便各執行緒管理自己的狀態而引用的乙個機制。

每個threadlocal內部都有乙個threadlocalmap,他儲存的key是threadlocal的例項,他的值是當前執行緒的區域性變數的副本的值。

Java(面試) 面試?別再問我睡眠排序了!

博主今天跟大家聊一聊睡眠排序,皮一下很開心!沒聽過睡眠排序?不要覺得丟臉,我也是剛知道的!說起排序,大家肯定只知道快排,氣泡排序等!然而今天看到一種睡眠排序,簡直是顛覆三觀,毀天滅地,確實是達到排序的目的了!而且思路清奇,著實可以拿出來分享分享 假設,入參是乙個亂序的陣列!那如何進行排序輸出呢?步驟...

拜託,面試別再問我跳表了!

跳表是乙個隨機化的資料結構,實質就是一種可以進行二分查詢的有序鍊錶。跳表在原有的有序鍊錶上面增加了多級索引,通過索引來實現快速查詢。跳表不僅能提高搜尋效能,同時也可以提高插入和刪除操作的效能。考慮乙個有序鍊錶,我們要查詢3 7 17這幾個元素,我們只能從頭開始遍歷鍊錶,直到查詢到元素為止。上述這個鍊...

拜託,面試別再問我TopK了!!!

除非校招,我在面試過程中從不問topk這個問題,預設大家都知道。將n個數排序之後,取出最大的k個 即為所得。sort arr,1,n return arr 1,k o n lg n 明明只需要topk,卻將全域性都排序了,這也是這個方法複雜度非常高的原因。那能不能不全域性排序,而只區域性排序呢?這就...