更新時(shí)間:2020-02-10 10:25:31 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽2884次
1.什么是活鎖、饑餓、無(wú)鎖、死鎖?
死鎖、活鎖、饑餓是關(guān)于多線程是否活躍出現(xiàn)的運(yùn)行阻塞障礙問(wèn)題,如果線程出現(xiàn)了這三種情況,即線程不再活躍,不能再正常地執(zhí)行下去了。
死鎖
死鎖是多線程中最差的一種情況,多個(gè)線程相互占用對(duì)方的資源的鎖,而又相互等對(duì)方釋放鎖,此時(shí)若無(wú)外力干預(yù),這些線程則一直處理阻塞的假死狀態(tài),形成死鎖。
舉個(gè)例子,A同學(xué)搶了B同學(xué)的鋼筆,B同學(xué)搶了A同學(xué)的書(shū),兩個(gè)人都相互占用對(duì)方的東西,都在讓對(duì)方先還給自己自己再還,這樣一直爭(zhēng)執(zhí)下去等待對(duì)方還而又得不到解決,
老師知道此事后就讓他們相互還給對(duì)方,這樣在外力的干預(yù)下他們才解決,當(dāng)然這只是個(gè)例子沒(méi)有老師他們也能很好解決,計(jì)算機(jī)不像人如果發(fā)現(xiàn)這種情況沒(méi)有外力干預(yù)還是會(huì)一直阻塞下去的。
活鎖
活鎖這個(gè)概念大家應(yīng)該很少有人聽(tīng)說(shuō)或理解它的概念,而在多線程中這確實(shí)存在。
活鎖恰恰與死鎖相反,死鎖是大家都拿不到資源都占用著對(duì)方的資源,而活鎖是拿到資源卻又相互釋放不執(zhí)行。
當(dāng)多線程中出現(xiàn)了相互謙讓,都主動(dòng)將資源釋放給別的線程使用,這樣這個(gè)資源在多個(gè)線程之間跳動(dòng)而又得不到執(zhí)行,這就是活鎖。
饑餓
我們知道多線程執(zhí)行中有線程優(yōu)先級(jí)這個(gè)東西,優(yōu)先級(jí)高的線程能夠插隊(duì)并優(yōu)先執(zhí)行,這樣如果優(yōu)先級(jí)高的線程一直搶占優(yōu)先級(jí)低線程的資源,導(dǎo)致低優(yōu)先級(jí)線程無(wú)法得到執(zhí)行,這就是饑餓。
當(dāng)然還有一種饑餓的情況,一個(gè)線程一直占著一個(gè)資源不放而導(dǎo)致其他線程得不到執(zhí)行,與死鎖不同的是饑餓在以后一段時(shí)間內(nèi)還是能夠得到執(zhí)行的,如那個(gè)占用資源的線程結(jié)束了并釋放了資源。
無(wú)鎖
無(wú)鎖,即沒(méi)有對(duì)資源進(jìn)行鎖定,即所有的線程都能訪問(wèn)并修改同一個(gè)資源,但同時(shí)只有一個(gè)線程能修改成功。
無(wú)鎖典型的特點(diǎn)就是一個(gè)修改操作在一個(gè)循環(huán)內(nèi)進(jìn)行,線程會(huì)不斷的嘗試修改共享資源,如果沒(méi)有沖突就修改成功并退出否則就會(huì)繼續(xù)下一次循環(huán)嘗試。
所以,如果有多個(gè)線程修改同一個(gè)值必定會(huì)有一個(gè)線程能修改成功,而其他修改失敗的線程會(huì)不斷重試直到修改成功。之前的文章我介紹過(guò)JDK的CAS原理及應(yīng)用即是無(wú)鎖的實(shí)現(xiàn)。
可以看出,無(wú)鎖是一種非常良好的設(shè)計(jì),它不會(huì)出現(xiàn)線程出現(xiàn)的跳躍性問(wèn)題,鎖使用不當(dāng)肯定會(huì)出現(xiàn)系統(tǒng)性能問(wèn)題,雖然無(wú)鎖無(wú)法全面代替有鎖,但無(wú)鎖在某些場(chǎng)合下是非常高效的。
2.線程和進(jìn)程的區(qū)別是什么?
進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑。
線程有自己的堆棧和局部變量,但線程之間沒(méi)有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。
但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。
3.Java實(shí)現(xiàn)線程有哪幾種方式?
?。?)繼承Thread類實(shí)現(xiàn)多線程
(2)實(shí)現(xiàn)Runnable接口方式實(shí)現(xiàn)多線程
?。?)使用ExecutorService、Callable、Future實(shí)現(xiàn)有返回結(jié)果的多線程
(4)通過(guò)線程池創(chuàng)建線程
4.啟動(dòng)線程方法start和run有什么區(qū)別?
只有調(diào)用了start方法,才會(huì)表現(xiàn)出多線程的特性,不同線程的run方法里面的代碼交替執(zhí)行。如果只是調(diào)用run方法,那么代碼還是同步執(zhí)行的,必須等待一個(gè)線程的run方法里面的代碼全部執(zhí)行完畢之后,另外一個(gè)線程才可以執(zhí)行其run方法里面的代碼。
5.怎么終止一個(gè)線程?如何優(yōu)雅地終止線程?
stop終止,不推薦。
6.一個(gè)線程的生命周期有哪幾種狀態(tài)?它們之間如何流轉(zhuǎn)的?
NEW:毫無(wú)疑問(wèn)表示的是剛創(chuàng)建的線程,還沒(méi)有開(kāi)始啟動(dòng)。
RUNNABLE:表示線程已經(jīng)觸發(fā)start方式調(diào)用,線程正式啟動(dòng),線程處于運(yùn)行中狀態(tài)。
BLOCKED:表示線程阻塞,等待獲取鎖,如碰到synchronized、lock等關(guān)鍵字等占用臨界區(qū)的情況,一旦獲取到鎖就進(jìn)行RUNNABLE狀態(tài)繼續(xù)運(yùn)行。
WAITING:表示線程處于無(wú)限制等待狀態(tài),等待一個(gè)特殊的事件來(lái)重新喚醒,如通過(guò)wait方法進(jìn)行等待的線程等待一個(gè)notify或者notifyAll方法,通過(guò)join方法進(jìn)行等待的線程等待目標(biāo)線程運(yùn)行結(jié)束而喚醒,一旦通過(guò)相關(guān)事件喚醒線程,線程就進(jìn)入了RUNNABLE狀態(tài)繼續(xù)運(yùn)行。
TIMED_WAITING:表示線程進(jìn)入了一個(gè)有時(shí)限的等待,如sleep(3000),等待3秒后線程重新進(jìn)行RUNNABLE狀態(tài)繼續(xù)運(yùn)行。
TERMINATED:表示線程執(zhí)行完畢后,進(jìn)行終止?fàn)顟B(tài)。需要注意的是,一旦線程通過(guò)start方法啟動(dòng)后就再也不能回到初始NEW狀態(tài),線程終止后也不能再回到RUNNABLE狀態(tài)。
7.線程中的wait和sleep方法有什么區(qū)別?
這個(gè)問(wèn)題常問(wèn),sleep方法和wait方法都可以用來(lái)放棄CPU一定的時(shí)間,不同點(diǎn)在于如果線程持有某個(gè)對(duì)象的監(jiān)視器,sleep方法不會(huì)放棄這個(gè)對(duì)象的監(jiān)視器,wait方法會(huì)放棄這個(gè)對(duì)象的監(jiān)視器。
8.多線程同步有哪幾種方法?
Synchronized關(guān)鍵字,Lock鎖實(shí)現(xiàn),分布式鎖等。
9.多線程有什么用?
1)發(fā)揮多核CPU的優(yōu)勢(shì)
隨著工業(yè)的進(jìn)步,現(xiàn)在的筆記本、臺(tái)式機(jī)乃至商用的應(yīng)用服務(wù)器至少也都是雙核的,4核、8核甚至16核的也都不少見(jiàn),如果是單線程的程序,那么在雙核CPU上就浪費(fèi)了50%,在4核CPU上就浪費(fèi)了75%。
單核CPU上所謂的"多線程"那是假的多線程,同一時(shí)間處理器只會(huì)處理一段邏輯,只不過(guò)線程之間切換得比較快,看著像多個(gè)線程"同時(shí)"運(yùn)行罷了。
多核CPU上的多線程才是真正的多線程,它能讓你的多段邏輯同時(shí)工作,多線程,可以真正發(fā)揮出多核CPU的優(yōu)勢(shì)來(lái),達(dá)到充分利用CPU的目的。
2)防止阻塞
從程序運(yùn)行效率的角度來(lái)看,單核CPU不但不會(huì)發(fā)揮出多線程的優(yōu)勢(shì),反而會(huì)因?yàn)樵趩魏薈PU上運(yùn)行多線程導(dǎo)致線程上下文的切換,而降低程序整體的效率。
但是單核CPU我們還是要應(yīng)用多線程,就是為了防止阻塞。試想,如果單核CPU使用單線程,那么只要這個(gè)線程阻塞了,比方說(shuō)遠(yuǎn)程讀取某個(gè)數(shù)據(jù)吧,對(duì)端遲遲未返回又沒(méi)有設(shè)置超時(shí)時(shí)間,那么你的整個(gè)程序在數(shù)據(jù)返回回來(lái)之前就停止運(yùn)行了。
多線程可以防止這個(gè)問(wèn)題,多條線程同時(shí)運(yùn)行,哪怕一條線程的代碼執(zhí)行讀取數(shù)據(jù)阻塞,也不會(huì)影響其它任務(wù)的執(zhí)行。
3)便于建模
這是另外一個(gè)沒(méi)有這么明顯的優(yōu)點(diǎn)了。假設(shè)有一個(gè)大的任務(wù)A,單線程編程,那么就要考慮很多,建立整個(gè)程序模型比較麻煩。但是如果把這個(gè)大的任務(wù)A分解成幾個(gè)小任務(wù),任務(wù)B、任務(wù)C、任務(wù)D,分別建立程序模型,并通過(guò)多線程分別運(yùn)行這幾個(gè)任務(wù),那就簡(jiǎn)單很多了。
10.多線程之間如何進(jìn)行通信?
wait/notify
以上就是動(dòng)力節(jié)點(diǎn)Java培訓(xùn)機(jī)構(gòu)小編介紹的“2020年Java多線程面試題大全”的內(nèi)容,希望對(duì)大家有幫助,如有疑問(wèn),請(qǐng)?jiān)诰€咨詢,有專業(yè)老師隨時(shí)為你服務(wù)。
相關(guān)推薦
相關(guān)閱讀
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時(shí)間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)
初級(jí) 202925
初級(jí) 203221
初級(jí) 202629
初級(jí) 203743