1.Thread線程
線程中start和run方法有什么區(qū)別砰盐?wait和sleep方法的不同肿仑?sleep() 、join()腥泥、yield()有什么區(qū)別匾南?
答:run()方法:在本線程內(nèi)調(diào)用該Runnable對象的run()方法,可以重復(fù)多次調(diào)用蛔外;
start()方法:啟動一個(gè)線程蛆楞,調(diào)用該Runnable對象的run()方法,不能多次啟動一個(gè)線程冒萄;
wait和sleep方法區(qū)別:
1.sleep 是線程類(Thread)的方法,導(dǎo)致此線程暫停執(zhí)行指定時(shí)間橙数,給執(zhí)行機(jī)會給其他線程尊流,但是監(jiān)控狀態(tài)依然保持,到時(shí)后會自動恢復(fù)灯帮,調(diào)用sleep 不會釋放對象鎖崖技。由于沒有釋放對象鎖逻住,所以不能調(diào)用里面的同步方法。
sleep()使當(dāng)前線程進(jìn)入停滯狀態(tài)(阻塞當(dāng)前線程)迎献,讓出CUP的使用瞎访、目的是不讓當(dāng)前線程獨(dú)自霸占該進(jìn)程所獲的CPU資源,以留一定時(shí)間給其他線程執(zhí)行的機(jī)會;
sleep()是Thread類的Static(靜態(tài))的方法吁恍;因此他不能改變對象的機(jī)鎖扒秸,所以當(dāng)在一個(gè)Synchronized塊中調(diào)用Sleep()方法是,線程雖然休眠了冀瓦,但是對象的機(jī)鎖并木有被釋放伴奥,其他線程無法訪問這個(gè)對象(即使睡著也持有對象鎖)。
在sleep()休眠時(shí)間期滿后翼闽,該線程不一定會立即執(zhí)行拾徙,這是因?yàn)槠渌€程可能正在運(yùn)行而且沒有被調(diào)度為放棄執(zhí)行,除非此線程具有更高的優(yōu)先級感局。
wait()方法是Object類里的方法尼啡;當(dāng)一個(gè)線程執(zhí)行到wait()方法時(shí),它就進(jìn)入到一個(gè)和該對象相關(guān)的等待池中询微,同時(shí)失去(釋放)了對象的機(jī)鎖(暫時(shí)失去機(jī)鎖崖瞭,wait(long timeout)超時(shí)時(shí)間到后還需要返還對象鎖);可以調(diào)用里面的同步方法拓提,其他線程可以訪問读恃;
wait()使用notify或者notifyAlll或者指定睡眠時(shí)間來喚醒當(dāng)前等待池中的線程。
wiat()必須放在synchronized block中代态,否則會在program runtime時(shí)扔出”java.lang.IllegalMonitorStateException“異常
2.sleep必須捕獲異常寺惫,而wait,notify和notifyAll不需要捕獲異常
sleep方法屬于Thread類中方法蹦疑,表示讓一個(gè)線程進(jìn)入睡眠狀態(tài)西雀,等待一定的時(shí)間之后,自動醒來進(jìn)入到可運(yùn)行狀態(tài)歉摧,不會馬上進(jìn)入運(yùn)行狀態(tài)艇肴,因?yàn)榫€程調(diào)度機(jī)制恢復(fù)線程的運(yùn)行也需要時(shí)間,一個(gè)線程對象調(diào)用了sleep方法之后叁温,并不會釋放他所持有的所有對象鎖再悼,所以也就不會影響其他進(jìn)程對象的運(yùn)行。但在sleep的過程中過程中有可能被其他對象調(diào)用它的interrupt(),產(chǎn)生InterruptedException異常膝但,如果你的程序不捕獲這個(gè)異常冲九,線程就會異常終止,進(jìn)入TERMINATED狀態(tài)跟束,如果你的程序捕獲了這個(gè)異常莺奸,那么程序就會繼續(xù)執(zhí)行catch語句塊(可能還有finally語句塊)以及以后的代碼丑孩。
注意sleep()方法是一個(gè)靜態(tài)方法,也就是說他只對當(dāng)前對象有效灭贷,通過t.sleep()讓t對象進(jìn)入sleep温学,這樣的做法是錯(cuò)誤的,它只會是使當(dāng)前線程被sleep 而不是t線程
wait屬于Object的成員方法甚疟,一旦一個(gè)對象調(diào)用了wait方法仗岖,必須要采用notify()和notifyAll()方法喚醒該進(jìn)程;如果線程擁有某個(gè)或某些對象的同步鎖,那么在調(diào)用了wait()后古拴,這個(gè)線程就會釋放它持有的所有同步資源箩帚,而不限于這個(gè)被調(diào)用了wait()方法的對象。wait()方法也同樣會在wait的過程中有可能被其他對象調(diào)用interrupt()方法而產(chǎn)生
3.sleep()是讓某個(gè)線程暫停運(yùn)行一段時(shí)間,其控制范圍是由當(dāng)前線程決定,也就是說,在線程里面決定.好比如說,我要做的事情是 "點(diǎn)火->燒水->煮面",而當(dāng)我點(diǎn)完火之后我不立即燒水,我要休息一段時(shí)間再燒.對于運(yùn)行的主動權(quán)是由我的流程來控制.
而wait(),首先,這是由某個(gè)確定的對象來調(diào)用的,將這個(gè)對象理解成一個(gè)傳話的人,當(dāng)這個(gè)人在某個(gè)線程里面說"暫停!",也是 thisOBJ.wait(),這里的暫停是阻塞,還是"點(diǎn)火->燒水->煮飯",thisOBJ就好比一個(gè)監(jiān)督我的人站在我旁邊,本來該線 程應(yīng)該執(zhí)行1后執(zhí)行2,再執(zhí)行3,而在2處被那個(gè)對象喊暫停,那么我就會一直等在這里而不執(zhí)行3,但正個(gè)流程并沒有結(jié)束,我一直想去煮飯,但還沒被允許, 直到那個(gè)對象在某個(gè)地方說"通知暫停的線程啟動!",也就是thisOBJ.notify()的時(shí)候,那么我就可以煮飯了,這個(gè)被暫停的線程就會從暫停處 繼續(xù)執(zhí)行.
yield方法:暫停當(dāng)前正在執(zhí)行的線程對象黄痪。
yield()只是使當(dāng)前線程重新回到可執(zhí)行狀態(tài)紧帕,所以執(zhí)行yield()的線程有可能在進(jìn)入到可執(zhí)行狀態(tài)后馬上又被執(zhí)行。
yield()只能使同優(yōu)先級或更高優(yōu)先級的線程有執(zhí)行的機(jī)會桅打。?
join方法:等待該線程終止是嗜。
等待調(diào)用join方法的線程結(jié)束,再繼續(xù)執(zhí)行挺尾。如:t.join();//主要用于等待t線程運(yùn)行結(jié)束鹅搪,若無此句,main則會執(zhí)行完畢遭铺,導(dǎo)致結(jié)果不可預(yù)測丽柿。
為什么我們調(diào)用start()方法時(shí)會執(zhí)行run()方法?
答:因?yàn)轭怲hread中的start方法中魂挂,調(diào)用了Thread中的run方法甫题。順便說下,類A繼承了Tread類涂召,在A中寫run方法坠非,就會覆蓋掉Thread中的run方法,所以此時(shí)調(diào)用start方法后果正,實(shí)現(xiàn)的是自己的run方法體里面的代碼炎码。
為什么我們不能直接調(diào)用run()方法?
答:如果我們直接調(diào)用子線程的run()方法秋泳,其方法還是運(yùn)行在主線程中潦闲,代碼在程序中是順序執(zhí)行的,所以不會有解決耗時(shí)操作的問題迫皱。所以不能直接調(diào)用線程的run()方法歉闰,只有子線程開始了,才會有異步的效果。當(dāng)thread.start()方法執(zhí)行了以后新娜,子線程才會執(zhí)行run()方法,這樣的效果和在主線程中直接調(diào)用run()方法的效果是截然不同的既绩。
Java 中如何停止一個(gè)線程概龄?
答:終止線程的三種方法:
1. 使用退出標(biāo)志,使線程正常退出饲握,也就是當(dāng)run方法完成后線程終止私杜。
2. 使用stop方法強(qiáng)行終止線程(這個(gè)方法不推薦使用,因?yàn)閟top和suspend救欧、resume一樣衰粹,也可能發(fā)生不可預(yù)料的結(jié)果)。
3. 使用interrupt方法中斷線程笆怠。
stop() 和 suspend() 方法為何不推薦使用铝耻?
答:stop()方法作為一種粗暴的線程終止行為,在線程終止之前沒有對其做任何的清除操作蹬刷,因此具有固有的不安全性瓢捉。 用Thread.stop()方法來終止線程將會釋放該線程對象已經(jīng)鎖定的所有監(jiān)視器。如果以前受這些監(jiān)視器保護(hù)的任何對象都處于不連貫狀態(tài)办成,那么損壞的對象對其他線程可見泡态,這有可能導(dǎo)致不安全的操作。?由于上述原因迂卢,因此不應(yīng)該使用stop()方法某弦,而應(yīng)該在自己的Thread類中置入一個(gè)標(biāo)志,用于控制目標(biāo)線程是活動還是停止而克。如果該標(biāo)志指示它要停止運(yùn)行靶壮,可使其結(jié)束run()方法。如果目標(biāo)線程等待很長時(shí)間拍摇,則應(yīng)使用interrupt()方法來中斷該等待亮钦。
suspend()方法 該方法已經(jīng)遭到反對,因?yàn)樗哂泄逃械乃梨i傾向充活。調(diào)用suspend()方法的時(shí)候蜂莉,目標(biāo)線程會停下來。如果目標(biāo)線程掛起時(shí)在保護(hù)關(guān)鍵系統(tǒng)資源的監(jiān)視器上保持有鎖混卵,則在目標(biāo)線程重新開始以前映穗,其他線程都不能訪問該資源。除非被掛起的線程恢復(fù)運(yùn)行幕随。對任何其他線程來說蚁滋,如果想恢復(fù)目標(biāo)線程,同時(shí)又試圖使用任何一個(gè)鎖定的資源,就會造成死鎖辕录。由于上述原因睦霎,因此不應(yīng)該使用suspend()方法,而應(yīng)在自己的thread類中置入一個(gè)標(biāo)志走诞,用于控制線程是活動還是掛起副女。如果標(biāo)志指出線程應(yīng)該掛起,那么用wait()方法命令其進(jìn)入等待狀態(tài)蚣旱。如果標(biāo)志指出線程應(yīng)當(dāng)恢復(fù)碑幅,那么用notify()方法重新啟動線程。
2.多線程
說一說多線程原理塞绿,如果線程過多,會怎樣?多線程的優(yōu)點(diǎn)沟涨?同時(shí)多線程的缺點(diǎn)?
答:多線程的原理
同一時(shí)間內(nèi)异吻,CPU只能處理1條線程裹赴,只有1條線程在工作(執(zhí)行);多線程并發(fā)(同時(shí))執(zhí)行,其實(shí)是CPU快速地在多條線程之間調(diào)度(切換)诀浪。如果CPU調(diào)度線程的時(shí)間足夠快篮昧,就造成了多線程并發(fā)執(zhí)行的假象。
多線程的好處:
1.使用線程可以把占據(jù)時(shí)間長的程序中的任務(wù)放到后臺去處理
2.用戶界面更加吸引人,這樣比如用戶點(diǎn)擊了一個(gè)按鈕去觸發(fā)某件事件的處理,可以彈出一個(gè)進(jìn)度條來顯示處理的進(jìn)度
3.程序的運(yùn)行效率可能會提高
4.在一些等待的任務(wù)實(shí)現(xiàn)上如用戶輸入,文件讀取和網(wǎng)絡(luò)收發(fā)數(shù)據(jù)等,線程就比較有用了.
多線程的缺點(diǎn):
1.如果有大量的線程,會影響性能,因?yàn)椴僮飨到y(tǒng)需要在它們之間切換.
2.更多的線程需要更多的內(nèi)存空間
3.線程中止需要考慮對程序運(yùn)行的影響.
4.通常塊模型數(shù)據(jù)是在多個(gè)線程間共享的,需要防止線程死鎖情況的發(fā)生
現(xiàn)在有T1笋妥、T2懊昨、T3三個(gè)線程,你怎樣保證T2在T1執(zhí)行完后執(zhí)行春宣,T3在T2執(zhí)行完后執(zhí)行酵颁?
答:假設(shè)現(xiàn)在有兩個(gè)線程A帆离、B蝌以。如果在A的run方法中調(diào)用B.join(),表示A需要在B線程上面等待框咙,也就是需要在B線程執(zhí)行完成之后才能再次執(zhí)行嚷辅。了解這個(gè)概念之后簿姨,這個(gè)問題就很簡單了,java代碼如下:
Thread t1 = new Thread(new T1());
Thread t2 = new Thread(new T2());
Thread t3 = new Thread(new T3());
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();?
在Java中Lock接口比synchronized塊的優(yōu)勢是什么簸搞?
答:能夠顯示地獲取和釋放鎖扁位,鎖的運(yùn)用更靈活
可以方便地實(shí)現(xiàn)公平鎖
能夠響應(yīng)中斷,非阻塞獲取鎖
3.線程池
線程池的關(guān)閉方式有幾種趁俊,各自的區(qū)別是什么域仇?線程池中submit() 和 execute()方法有什么區(qū)別?
答:我們知道寺擂,使用shutdownNow方法暇务,可能會引起報(bào)錯(cuò)泼掠,使用shutdown方法可能會導(dǎo)致線程關(guān)閉不了。
所以當(dāng)我們使用shutdownNow方法關(guān)閉線程池時(shí)垦细,一定要對任務(wù)里進(jìn)行異常捕獲择镇。
當(dāng)我們使用shuwdown方法關(guān)閉線程池時(shí),一定要確保任務(wù)里不會有永久阻塞等待的邏輯括改,否則線程池就關(guān)閉不了沐鼠。
最后,一定要記得叹谁,shutdownNow和shuwdown調(diào)用完,線程池并不是立馬就關(guān)閉了乘盖,要想等待線程池關(guān)閉焰檩,還需調(diào)用awaitTermination方法來阻塞等待。
1订框、接收的參數(shù)不一樣
2析苫、submit有返回值,而execute沒有
用到返回值的例子穿扳,比如說我有很多個(gè)做validation的task衩侥,我希望所有的task執(zhí)行完,然后每個(gè)task告訴我它的執(zhí)行結(jié)果矛物,是成功還是失敗茫死,如果是失敗,原因是什么履羞。
然后我就可以把所有失敗的原因綜合起來發(fā)給調(diào)用者峦萎。
個(gè)人覺得cancel execution這個(gè)用處不大,很少有需要去取消執(zhí)行的忆首。
而最大的用處應(yīng)該是第二點(diǎn)爱榔。
3、submit方便Exception處理
意思就是如果你在你的task里會拋出checked或者unchecked exception糙及,
而你又希望外面的調(diào)用者能夠感知這些exception并做出及時(shí)的處理详幽,那么就需要用到submit,通過捕獲Future.get拋出的異常浸锨。