資源描述:
《java并發(fā)編程:深入剖析threadlocal-java開(kāi)發(fā)java經(jīng)驗(yàn)技巧》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在工程資料-天天文庫(kù)。
1、Java并發(fā)編程:深入剖權(quán)「ThrcadLocal-編程開(kāi)發(fā)技術(shù)Java并發(fā)編程:深入剖析ThreadLocal原文出處:海子想必很多朋友對(duì)ThreadLocal并不陌生,今天我們就來(lái)一起探討下ThreadLocal的使用方法和實(shí)現(xiàn)原理。首先,本文先談一下對(duì)ThreadLocal的理解,然后根據(jù)ThreadLocal類的源碼分析了其實(shí)現(xiàn)原理和使用需要注意的地方,最后給出了兩個(gè)應(yīng)用場(chǎng)景。以下是木文目錄大綱:一.對(duì)ThreadLocal的理解二.深入解析ThreadLocal類三.ThreadLocal的應(yīng)用場(chǎng)景若有不正之處請(qǐng)多多諒解,并歡迎批評(píng)指正。一?對(duì)ThreadLocal的理解Thread
2、Local,很多地方叫做線程本地變量,也有些地方叫做線程本地存儲(chǔ),其實(shí)意思差不多??赡芎芏嚯居讯贾繲hreadLocal為變量在每個(gè)線程屮都創(chuàng)建了一個(gè)副本,那么每個(gè)線程可以訪問(wèn)自己內(nèi)部的副本變量。這句話從字面上看起來(lái)很容易理解,但是真正理解并不是那么容易。我們還是先來(lái)看-個(gè)例子:classConnectionManager{privatestaticConnectionconnect二null;publicstaticConneclionopenConnection(){if(cormect==null){connect=DrivcrManagcr?gctConncction();}fetu
3、rnconnect;}publicstaticvoidcloscConnection(){if(connect!二null)connect.close();假設(shè)有這樣一個(gè)數(shù)據(jù)庫(kù)鏈接管理類,這段代碼在單線程中使用是沒(méi)有任何問(wèn)題的,但是如果在多線程中使用呢?很顯然,在多線程中使用會(huì)存在線程安全問(wèn)題:第一,這里面的2個(gè)方法都沒(méi)有進(jìn)行同步,很可能在opcnConncction方法中會(huì)多次創(chuàng)建connect;第二,由于connect是共享變量,那么必然在調(diào)用connect的地方需要使用到同步來(lái)保障線程安全,因?yàn)楹芸赡芤粋€(gè)線程在使用connect進(jìn)行數(shù)據(jù)庫(kù)操作,而另外一個(gè)線程調(diào)用closeconnecti
4、on關(guān)閉鏈接。所以出于線程安全的考慮,必須將這段代碼的兩個(gè)方法進(jìn)行同步處理,并且在調(diào)用connect的地方需要進(jìn)行同步處理。這樣將會(huì)大大影響程序執(zhí)行效率,因?yàn)橐粋€(gè)線程在使用connect進(jìn)行數(shù)據(jù)庫(kù)操作的時(shí)候,其他線程只有等待。那么大家來(lái)仔細(xì)分析一下這個(gè)問(wèn)題,這地方到底需不需要將connect變量進(jìn)行共享?事實(shí)上,是不需耍的。假如每個(gè)線程中都有一個(gè)connect變量,各個(gè)線程之間對(duì)connect變量的訪問(wèn)實(shí)際上是沒(méi)有依賴關(guān)系的,即一個(gè)線程不需要關(guān)心其他線程是否對(duì)這個(gè)connect進(jìn)行了修改的。到這里,可能會(huì)有朋友想到,既然不需要在線程Z間共享這個(gè)變量,可以直接這樣處理,在毎個(gè)需要使用數(shù)據(jù)庫(kù)連接的
5、方法中具休使用時(shí)才創(chuàng)建數(shù)據(jù)庫(kù)鏈接,然后在方法調(diào)用完畢再釋放這個(gè)連接。比如下面這樣:classConnect!onManager{privateConnectionconnect二null;publicConnectionopenConnection(){if(connect二二null){connect二DrivcrManagcr.gctConncction();}returnconnect;publicvoidcloscConncction(){if(connect!二null)connect.close();classDao{publicvoidinsert(){ConnectionMan
6、agerconnectionManager二newConnectionManager();Connectionconnection=connectionManager.openConnection();//使用connection進(jìn)彳亍操作conncctionMemagcr?closcConncction();}這樣處理確實(shí)也沒(méi)有任何問(wèn)題,由于每次都是在方法內(nèi)部創(chuàng)建的連接,那么線程之間自然不存在線程安全問(wèn)題。但是這樣會(huì)有一個(gè)致命的影響:導(dǎo)致服務(wù)器壓力非常大,并且嚴(yán)重影響程序執(zhí)行性能。由于在方法中需要頻繁地開(kāi)啟和關(guān)閉數(shù)據(jù)庫(kù)連接,這樣不盡嚴(yán)重影響程序執(zhí)行效率,述可能導(dǎo)致服務(wù)器壓力巨大。那么這種情況
7、下使用ThreadLocal是再適合不過(guò)的了,因?yàn)門(mén)hreadLocal在每個(gè)線程中對(duì)該變量會(huì)創(chuàng)建一個(gè)副本,即毎個(gè)線程內(nèi)部都會(huì)有一個(gè)該變量,且在線程內(nèi)部任何地方都可以使用,線程之間互不影響,這樣一來(lái)就不存在線程安全問(wèn)題,也不會(huì)嚴(yán)重影響程序執(zhí)行性能。但是要注意,雖然ThreadLocal能夠解決上面說(shuō)的問(wèn)題,但是由于在每個(gè)線程中都創(chuàng)建了副本,所以要考慮它對(duì)資源的消耗,比如內(nèi)存的占用會(huì)比不使用Thre