提到ThreadLocal被提到應(yīng)用最多的是session管理和數(shù)據(jù)庫(kù)鏈接管理,這里以數(shù)據(jù)訪(fǎng)問(wèn)為例幫助你理解ThreadLocal:
如下數(shù)據(jù)庫(kù)管理類(lèi)在單線(xiàn)程使用是沒(méi)有任何問(wèn)題的
很顯然,在多線(xiàn)程中使用會(huì)存在線(xiàn)程安全問(wèn)題:,這里面的2個(gè)方法都沒(méi)有進(jìn)行同步,很可能在openConnection方法中會(huì)多次創(chuàng)建connect;第二,由于connect是共享變量,那么必然在調(diào)用connect的地方需要使用到同步來(lái)保障線(xiàn)程安全,因?yàn)楹芸赡芤粋€(gè)線(xiàn)程在使用connect進(jìn)行數(shù)據(jù)庫(kù)操作,而另外一個(gè)線(xiàn)程調(diào)用closeConnection關(guān)閉鏈接。
為了解決上述線(xiàn)程安全的問(wèn)題,考慮:互斥同步
你可能會(huì)說(shuō),將這段代碼的兩個(gè)方法進(jìn)行同步處理,并且在調(diào)用connect的地方需要進(jìn)行同步處理,比如用Synchronized或者ReentrantLock互斥鎖。
這里再拋出一個(gè)問(wèn)題:這地方到底需不需要將connect變量進(jìn)行共享?
事實(shí)上,是不需要的。假如每個(gè)線(xiàn)程中都有一個(gè)connect變量,各個(gè)線(xiàn)程之間對(duì)connect變量的訪(fǎng)問(wèn)實(shí)際上是沒(méi)有依賴(lài)關(guān)系的,即一個(gè)線(xiàn)程不需要關(guān)心其他線(xiàn)程是否對(duì)這個(gè)connect進(jìn)行了修改的。
即改后的代碼可以這樣:
這樣處理確實(shí)也沒(méi)有任何問(wèn)題,由于每次都是在方法內(nèi)部創(chuàng)建的連接,那么線(xiàn)程之間自然不存在線(xiàn)程安全問(wèn)題。但是這樣會(huì)有一個(gè)致命的影響:導(dǎo)致服務(wù)器壓力非常大,并且嚴(yán)重影響程序執(zhí)行性能。由于在方法中需要頻繁地開(kāi)啟和關(guān)閉數(shù)據(jù)庫(kù)連接,這樣不僅嚴(yán)重影響程序執(zhí)行效率,還可能導(dǎo)致服務(wù)器壓力巨大。
這時(shí)候ThreadLocal登場(chǎng)了
那么這種情況下使用ThreadLocal是再適合不過(guò)的了,因?yàn)門(mén)hreadLocal在每個(gè)線(xiàn)程中對(duì)該變量會(huì)創(chuàng)建一個(gè)副本,即每個(gè)線(xiàn)程內(nèi)部都會(huì)有一個(gè)該變量,且在線(xiàn)程內(nèi)部任何地方都可以使用,線(xiàn)程之間互不影響,這樣一來(lái)就不存在線(xiàn)程安全問(wèn)題,也不會(huì)嚴(yán)重影響程序執(zhí)行性能。
下面就是網(wǎng)上出現(xiàn)最多的例子: