java 内部thread_Java代码质量改进之:使用ThreadLocal维护线程内部变量
在上文中,《Java代碼質(zhì)量改進(jìn)之:同步對(duì)象的選擇》,我們提出了一個(gè)場(chǎng)景:火車站有3個(gè)售票窗口,同時(shí)在售一趟列車的100個(gè)座位。我們通過鎖定一個(gè)靠譜的同步對(duì)象,完成了上面的功能。
現(xiàn)在,讓我們反過來(lái),每個(gè)窗口負(fù)責(zé)一趟車。比如一號(hào)窗口就賣1號(hào)列車的票,二號(hào)窗口就賣2號(hào)列車的票。不過它們需要同時(shí)開始賣票。
一:ThreadLocal的最簡(jiǎn)應(yīng)用
首先,既然是各賣各的火車了,那么,就不需要同步了。于是代碼又回歸到:
但是當(dāng)前的代碼肯定是不對(duì)的,每個(gè)線程訪問的都是同一個(gè)火車的ticket,并且還會(huì)出現(xiàn)超售現(xiàn)象。要保證每new一個(gè)窗口出來(lái),就有一趟自己的列車,我們就可以用到ThreadLocal對(duì)象了。
讓我們首先替換掉ticket變量,改為:
然后,售票的代碼改為:
雖然ticket依然是一個(gè)static變量,但是,運(yùn)行程序你會(huì)發(fā)現(xiàn),新起一個(gè)線程,不同的線程還是會(huì)擁有自己的ticket,不會(huì)互相干擾。也就是實(shí)現(xiàn)了每個(gè)窗口賣自己那趟車的目標(biāo)。
二:ThreadLocal?VS?實(shí)例變量
每一個(gè)程序員都應(yīng)該是杠精。為什么,因?yàn)榛剡^神來(lái)的我們發(fā)現(xiàn),只要回到第一段代碼中,把ticket中的static去掉,就能達(dá)到同樣的目的:
試下上面的代碼,是不是也能達(dá)到各賣各的目的?
我們是腦袋被門板擠了,才想出來(lái)一個(gè)TheadLocal這樣的復(fù)雜方案嗎?
如果單純說上面的這段代碼,是的。但是,還有很多的場(chǎng)合,是ThreadLocal的用武之處。比如,我們并不永遠(yuǎn)使用extends?Thead的方式來(lái)寫多線程,我們還可能用implements Runnable的方式來(lái)寫多線程(ps:還有更多的寫法哦),如下:
而在這種情況下,我們就不得不使用TheadLocal了,這里就不放出代碼了,大家可以試一下。
甚至,更進(jìn)一步的,我們是不是能夠把ticket這個(gè)變量放進(jìn)方法內(nèi)部呢,如果放入方法
內(nèi)部的話,我們同樣也是必須要使用ThreadLocal才能達(dá)到實(shí)現(xiàn)目的,如下:
總之,簡(jiǎn)單來(lái)說:當(dāng)要運(yùn)行的代碼本身不是很方便訪問當(dāng)前的線程實(shí)例的時(shí)候,就是ThreadLocal的用武之地。
三:ThreadLocal的應(yīng)用場(chǎng)景
ThreadLocal有這樣一些應(yīng)用場(chǎng)景,比如連接池管理、會(huì)話管理等等。
在連接池的管理中,當(dāng)我們需要獲取一個(gè)連接,就應(yīng)該為每一次獲取給出不同的連接。在web應(yīng)用中,請(qǐng)求是被線程池管理的,也就是說獲取連接這個(gè)行為不是單線程行為,所以我們最好就要設(shè)計(jì)成不同的線程不能獲取同一個(gè)連接,要保證能做到這樣,就應(yīng)該使用ThreadLocal了。
可能有人會(huì)表示,那不能設(shè)計(jì)成實(shí)例變量嗎?答案是:不能。因?yàn)?#xff0c;在web應(yīng)用中,線程都不是被我們自己管理的,所以,最佳的做法就是使用ThreadLocal。一個(gè)標(biāo)準(zhǔn)的做法如下:
最后作為補(bǔ)充,我們?cè)賮?lái)看看hibernate中ThreadLocal的應(yīng)用:
以下是廣告時(shí)間:最課程(http://zuikc.com)正在招收J(rèn)ava就業(yè)班學(xué)員,如果你想學(xué)習(xí)更多的Java高質(zhì)量代碼編寫方面的技巧,請(qǐng)聯(lián)系我們哦。
總結(jié)
以上是生活随笔為你收集整理的java 内部thread_Java代码质量改进之:使用ThreadLocal维护线程内部变量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xmind编写测试用例
- 下一篇: Java计算器