阿里一面 —— 什么是多线程?
馬上就要到金三銀四佳季了,是找工作的好時(shí)候,小伙伴們一定要把握好時(shí)機(jī),找到心儀的高薪工作。找工作就少不了面試,那我們從現(xiàn)在開始,多刷刷面試題,查缺補(bǔ)漏!!!
?
?
目錄
?什么是線程?線程和進(jìn)程的區(qū)別??
?創(chuàng)建線程有幾種方式??
?Runnable和Callable的區(qū)別??
?如何啟動(dòng)一個(gè)新線程、調(diào)用start和run方法的區(qū)別??
?線程有哪幾種狀態(tài)以及各種狀態(tài)之間的轉(zhuǎn)換??
?線程相關(guān)的基本方法??
?wait()和sleep()的區(qū)別??
?
?
?什么是線程?線程和進(jìn)程的區(qū)別??
?
線程:是進(jìn)程的一個(gè)實(shí)體,是 cpu 調(diào)度和分派的基本單位,是比進(jìn)程更小的
可以獨(dú)立運(yùn)行的基本單位。
進(jìn)程:具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),是操作
系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。
特點(diǎn):線程的劃分尺度小于進(jìn)程,這使多線程程序擁有高并發(fā)性,進(jìn)程在運(yùn)行
時(shí)各自內(nèi)存單元相互獨(dú)立,線程之間 內(nèi)存共享,這使多線程編程可以擁有更好
的性能和用戶體驗(yàn)。
?創(chuàng)建線程有幾種方式??
1.繼承Thread類并重寫 run 方法創(chuàng)建線程,實(shí)現(xiàn)簡(jiǎn)單但不可以繼承其他類
2.實(shí)現(xiàn)Runnable接口并重寫 run 方法。避免了單繼承局限性,編程更加靈活,實(shí)現(xiàn)解耦。
3..實(shí)現(xiàn) Callable接口并重寫 call 方法,創(chuàng)建線程。可以獲取線程執(zhí)行結(jié)果的返回值,并且可以拋出異常。
4.使用線程池創(chuàng)建(使用java.util.concurrent.Executor接口)
?Runnable和Callable的區(qū)別??
Runnable 接口 run 方法無返回值;Callable 接口 call 方法有返回值,支持泛型
Runnable 接口 run 方法只能拋出運(yùn)行時(shí)異常,且無法捕獲處理;Callable 接口 call 方法允許拋出異常,可以獲取異常信息
?如何啟動(dòng)一個(gè)新線程、調(diào)用start和run方法的區(qū)別??
線程對(duì)象調(diào)用run方法不開啟線程。僅是對(duì)象調(diào)用方法。
線程對(duì)象調(diào)用start開啟線程,并讓jvm調(diào)用run方法在開啟的線程中執(zhí)行
調(diào)用start方法可以啟動(dòng)線程,并且使得線程進(jìn)入就緒狀態(tài),而run方法只是thread的一個(gè)普通方法,還是在主線程中執(zhí)行。
?
?線程有哪幾種狀態(tài)以及各種狀態(tài)之間的轉(zhuǎn)換??
1. 第一是new->新建狀態(tài)。在生成線程對(duì)象,并沒有調(diào)用該對(duì)象的start方法,這是線程處于創(chuàng)建狀態(tài)。
2. 第二是Runnable->就緒狀態(tài)。當(dāng)調(diào)用了線程對(duì)象的start方法之后,該線程就進(jìn)入了就緒狀態(tài),但是此時(shí)線程調(diào)度程序還沒有把該線程設(shè)置為當(dāng)前線程,此時(shí)處于就緒狀態(tài)。
3. 第三是Running->運(yùn)行狀態(tài)。線程調(diào)度程序?qū)⑻幱诰途w狀態(tài)的線程設(shè)置為當(dāng)前線程,此時(shí)線程就進(jìn)入了運(yùn)行狀態(tài),開始運(yùn)行run函數(shù)當(dāng)中的代碼。
4. 第四是阻塞狀態(tài)。阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán),暫時(shí)停止運(yùn)行。直到線程進(jìn)入就緒狀態(tài),才有機(jī)會(huì)轉(zhuǎn)到運(yùn)行狀態(tài)。阻塞的情況分三種:
(1)等待 – 通過調(diào)用線程的wait()?方法,讓線程等待某工作的完成。
(2)超時(shí)等待 – 通過調(diào)用線程的sleep()?或join()或發(fā)出了I/O請(qǐng)求時(shí),線程會(huì)進(jìn)入到阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí)、或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài)。
(3)同步阻塞 – 線程在獲取synchronized同步鎖失敗(因?yàn)殒i被其它線程所占用),它會(huì)進(jìn)入同步阻塞狀態(tài)。
5. 第五是dead->死亡狀態(tài): 線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期.
?線程相關(guān)的基本方法??
線程相關(guān)的基本方法有 wait,notify,notifyAll,sleep,join,yield 等
1.線程等待(wait)
調(diào)用該方法的線程進(jìn)入 WAITING 狀態(tài),只有等待另外線程的通知或被中
斷才會(huì)返回,需要注意的是調(diào)用 wait()方法后,會(huì)釋放對(duì)象的鎖。因此,wait 方
法一般用在同步方法或同步代碼塊中。
2.線程睡眠(sleep)
sleep 導(dǎo)致當(dāng)前線程休眠,與 wait 方法不同的是 sleep 不會(huì)釋放當(dāng)前占
有的鎖,sleep(long)會(huì)導(dǎo)致線程進(jìn)入 TIMED-WATING 狀態(tài),而 wait()方法
會(huì)導(dǎo)致當(dāng)前線程進(jìn)入 WATING 狀態(tài).
3.線程讓步(yield)
yield 會(huì)使當(dāng)前線程讓出 CPU 執(zhí)行時(shí)間片,與其他線程一起重新競(jìng)爭(zhēng)
CPU 時(shí)間片。一般情況下,優(yōu)先級(jí)高的線程有更大的可能性成功競(jìng)爭(zhēng)得到 CPU
時(shí)間片,但這又不是絕對(duì)的,有的操作系統(tǒng)對(duì) 線程優(yōu)先級(jí)并不敏感。
4.線程中斷(interrupt)
中斷一個(gè)線程,其本意是給這個(gè)線程一個(gè)通知信號(hào),會(huì)影響這個(gè)線程內(nèi)部的
一個(gè)中斷標(biāo)識(shí)位。這個(gè)線程本身并不會(huì)因此而改變狀態(tài)(如阻塞,終止等)
5.Join 等待其他線程終止
join() 方法,等待其他線程終止,在當(dāng)前線程中調(diào)用一個(gè)線程的 join() 方
法,則當(dāng)前線程轉(zhuǎn)為阻塞狀態(tài),回到另一個(gè)線程結(jié)束,當(dāng)前線程再由阻塞狀態(tài)變
為就緒狀態(tài),等待 cpu 的寵幸.
6.線程喚醒(notify)
Object 類中的 notify() 方法,喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程,如
果所有線程都在此對(duì)象上等待,則會(huì)選擇喚醒其中一個(gè)線程,選擇是任意的,并
在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生,線程通過調(diào)用其中一個(gè) wait() 方法,在對(duì)象的監(jiān)視
器上等待,直到當(dāng)前的線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程,
被喚醒的線程將以常規(guī)方式與在該對(duì)象上主動(dòng)同步的其他所有線程進(jìn)行競(jìng)爭(zhēng)。類
似的方法還有 notifyAll() ,喚醒再次監(jiān)視器上等待的所有線程。
?wait()和sleep()的區(qū)別??
1. 來自不同的類
wait():來自O(shè)bject類;
sleep():來自Thread類;
2. 關(guān)于鎖的釋放:
wait():在等待的過程中會(huì)釋放鎖;
sleep():在等待的過程中不會(huì)釋放鎖
3. 使用的范圍:
wait():必須在同步代碼塊中使用;
sleep():可以在任何地方使用;
4. 是否需要捕獲異常
wait():不需要捕獲異常;
sleep():需要捕獲異常;
?
總結(jié)
以上是生活随笔為你收集整理的阿里一面 —— 什么是多线程?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 官方预告相机光学创新成果:小米12 Ul
- 下一篇: 宁德时代今日发布“麒麟电池”:能量密度超