更新時(shí)間:2021-06-23 15:52:49 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1947次
Java開(kāi)發(fā)線程特點(diǎn)基礎(chǔ)知識(shí)分享,線程提供的一些不太常用的方法及技術(shù)不管是初學(xué)者還是高級(jí)用戶或者是Java專(zhuān)家都需要了解。掌握線程、進(jìn)程、多線程、并發(fā)、并行、同步、異步、線程類(lèi)常見(jiàn)方法、線程生命周期、線程安全問(wèn)題、死鎖、生產(chǎn)者和消費(fèi)者等多線程核心知識(shí)點(diǎn)。

程序中的每個(gè)線程都有一個(gè)名字,創(chuàng)建線程的時(shí)候會(huì)給它分配一個(gè)簡(jiǎn)單的Java字符串來(lái)作為線程名。默認(rèn)的名字是”Thread-0″,“Thread-1″,“Thread-2″等。
線程名可變,可在運(yùn)行時(shí)修改它的名字,而不用在初始化的時(shí)候就指定好。name字段其實(shí)是一個(gè)簡(jiǎn)單的字符串對(duì)象,它能達(dá)到2³¹-1個(gè)字符那么長(zhǎng)足夠用了。這個(gè)名字并不是一個(gè)唯一性的標(biāo)識(shí),因此不同的線程也可以擁有同樣的線程名。還有一點(diǎn)不要把null用作線程名否則會(huì)拋出異常。
使用線程名來(lái)調(diào)試問(wèn)題
既然可以設(shè)置線程名,如果遵循一定的命名規(guī)則出問(wèn)題的時(shí)候排查起來(lái)就能更容易。在處理用戶請(qǐng)求的時(shí)候可以將事務(wù)ID追加到線程名后面,能減少排查問(wèn)題的時(shí)間。
線程還有一個(gè)有意思的屬性優(yōu)先級(jí)。線程的優(yōu)先級(jí)介于1(MINPRIORITY)到10(MAXPRIORITY)之間,主線程默認(rèn)是5(NORM_PRIORITY)。每個(gè)新線程都默認(rèn)繼承父線程的優(yōu)先級(jí),如果沒(méi)設(shè)置過(guò),所有線程的優(yōu)先級(jí)都是5。這個(gè)是通常被忽視的屬性,可以通過(guò)getPriority()與setPriority()方法來(lái)獲取及修改它的值。線程的構(gòu)造函數(shù)里是沒(méi)有這個(gè)功能。
什么地方會(huì)用到優(yōu)先級(jí)?
不是所有的線程都是平等的,有的線程需要立即引起CPU重視,而有些線程則只是后臺(tái)任務(wù)。優(yōu)先級(jí)就是用來(lái)把這些告訴給操作系統(tǒng)的線程調(diào)度器。在Takipi中開(kāi)發(fā)的一錯(cuò)誤跟蹤及排查的工具,負(fù)責(zé)處理用戶異常的線程的優(yōu)先級(jí)是MAX_PRIORITY,而那些只是在上報(bào)新的部署情況的線程,優(yōu)先級(jí)就要低一些。優(yōu)先級(jí)高的線程從JVM的線程調(diào)度器那得到的時(shí)間會(huì)多一些,但其實(shí)并非是這樣的。
在操作系統(tǒng)層面每一個(gè)新線程都會(huì)對(duì)應(yīng)一個(gè)本地線程,所設(shè)置的Java線程的優(yōu)先級(jí)會(huì)被轉(zhuǎn)化成本地線程的優(yōu)先級(jí),這個(gè)在各個(gè)平臺(tái)上不一樣。在Linux上可以打開(kāi)“-XX:+UseThreadPriorities”選項(xiàng)來(lái)啟用這項(xiàng)功能。線程優(yōu)先級(jí)只是所提供的一個(gè)建議,和Linux本地的優(yōu)先級(jí)相比Java線程的優(yōu)先級(jí)并不能覆蓋全所有的級(jí)別(Linux共有1到99個(gè)優(yōu)先級(jí),線程的優(yōu)先級(jí)在是-20到20之間)。最大的好處所設(shè)定的優(yōu)先級(jí)能在每個(gè)線程獲得的CPU時(shí)間上有所體現(xiàn),不過(guò)完全依賴(lài)于線程優(yōu)先級(jí)的做法不推薦。
ThreadLocal是在Thread類(lèi)之外實(shí)現(xiàn)的一個(gè)功能(java.lang.ThreadLocal),但它會(huì)為每個(gè)線程分別存儲(chǔ)一份唯一的數(shù)據(jù)。正如它的名字所說(shuō)的,它為線程提供了本地存儲(chǔ),也就是說(shuō)所創(chuàng)建出來(lái)變量對(duì)每個(gè)線程實(shí)例來(lái)說(shuō)都是唯一的。和線程名,線程優(yōu)先級(jí)類(lèi)似可以自定義出一些屬性,像存儲(chǔ)在Thread線程內(nèi)部一樣。
全局變量不是什么好事
ThreadLocal可以用來(lái)存儲(chǔ)事務(wù)ID。如果代碼中出現(xiàn)未捕獲異常的時(shí)候它就相當(dāng)有用了,最佳實(shí)踐是設(shè)置一個(gè)UncaughtExceptionHandler,這個(gè)是Thread類(lèi)本身就支持的,但是得自己去實(shí)現(xiàn)一下這個(gè)接口。一旦執(zhí)行到了UncaughtExceptionHandler里,幾乎沒(méi)有任何線索能夠知道到底發(fā)生了什么事情了。這會(huì)兒能獲取到的就只有Thread對(duì)象,之前導(dǎo)致異常發(fā)生的所有變量都無(wú)法再訪問(wèn)了,因?yàn)槟切家呀?jīng)被彈出了。一旦到了UncaughtExceptionHandler里,這個(gè)線程就只剩下最后一口氣了,唯一能抓住的最后一根稻草就是ThreadLocal。
Thread類(lèi)。程序中的每個(gè)線程都會(huì)有一個(gè)狀態(tài),是用戶狀態(tài)或是守護(hù)狀態(tài)。換句話說(shuō),前臺(tái)線程或是后臺(tái)線程,主線程默認(rèn)是用戶線程,每個(gè)新線程都會(huì)從創(chuàng)建它的線程中繼承線程狀態(tài)。如果把一個(gè)線程設(shè)置成守護(hù)線程,那么它所創(chuàng)建的所有線程都會(huì)被標(biāo)記成守護(hù)線程。如果程序中的所有線程都是守護(hù)線程的話,那么這個(gè)進(jìn)程便會(huì)終止??梢酝ㄟ^(guò)Boolean.setDaemon(true)和.isDaemon()方法來(lái)查看及設(shè)置線程狀態(tài)。
什么時(shí)候會(huì)用到守護(hù)線程?
如果進(jìn)程不必等到某個(gè)線程結(jié)束才能終止,那么這個(gè)線程就可以設(shè)置成守護(hù)線程。這省掉了正常關(guān)閉線程的那些麻煩事,可以立即將線程結(jié)束掉。換個(gè)角度來(lái)說(shuō),如果一個(gè)正在執(zhí)行某個(gè)操作的線程必須要正確地關(guān)閉掉否則就會(huì)出現(xiàn)不好的后果的話,那么這個(gè)線程就應(yīng)該是用戶線程。通常都是些關(guān)鍵的事務(wù),比方說(shuō),數(shù)據(jù)庫(kù)錄入或者更新這些操作不能中斷。
這里要講的會(huì)更靠近硬件,當(dāng)軟件遇上了硬件。處理器親和性使得能夠?qū)⒕€程或者進(jìn)程綁定到特定的CPU核上。這意味著只要是某個(gè)特定的線程,肯定只會(huì)在某個(gè)特定的CPU核上執(zhí)行。通常來(lái)講如何綁定是由操作系統(tǒng)的線程調(diào)度器根據(jù)它自己的邏輯來(lái)決定的,它很可能會(huì)將前面提到的線程優(yōu)先級(jí)也一并考慮進(jìn)來(lái)。
這么做的好處在于CPU緩存。如果某個(gè)線程只會(huì)在某個(gè)核上運(yùn)行,那么它的數(shù)據(jù)恰好在緩存里的概率就大大提高了。如果數(shù)據(jù)正好就在CPU緩存里,那么就沒(méi)有必要重新再?gòu)膬?nèi)存里加載了。所節(jié)省的這幾毫秒時(shí)間就能用在刀刃上,在這段時(shí)間里代碼可以馬上開(kāi)始執(zhí)行,也就能更好地利用所分配給它的CPU時(shí)間。當(dāng)然了,操作系統(tǒng)層面可能會(huì)存在某種優(yōu)化,硬件架構(gòu)當(dāng)然也是個(gè)很重要的因素,但利用了處理器的親和性至少能夠減小線程切換CPU的機(jī)率。
由于摻雜著多種因素處理器親和性到底對(duì)吞吐量有多大的影響,最好還是通過(guò)測(cè)試的方式來(lái)進(jìn)行證明。也許這個(gè)方法并不是總能顯著地提升性能,但至少有一個(gè)好處就是吞吐量會(huì)相對(duì)穩(wěn)定。親和策略可以細(xì)化到非常細(xì)的粒度上取決于具體想要什么,高頻交易行業(yè)便是這一策略最能大顯身手的場(chǎng)景之一。
以上就是動(dòng)力節(jié)點(diǎn)小編介紹的"學(xué)Java基礎(chǔ)線程的初學(xué)教程",希望對(duì)大家有幫助,如有疑問(wèn),請(qǐng)?jiān)诰€咨詢,有專(zhuān)業(yè)老師隨時(shí)為您服務(wù)。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)