
多線程的基本概念
1.進(jìn)程
進(jìn)程是操作系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位。
2.線程
線程是進(jìn)程中的一個(gè)執(zhí)行單元,負(fù)責(zé)當(dāng)前進(jìn)程中程序的執(zhí)行,一個(gè)進(jìn)程中至少有一個(gè)線程。
3.多線程
什么是多線程呢?即就是一個(gè)程序中有多個(gè)線程在同時(shí)執(zhí)行。
02
線程的生命周期
java中每個(gè)線程都需經(jīng)歷新生、就緒、運(yùn)行、阻塞和死亡五種狀態(tài),線程從新生到死亡的狀態(tài)變化稱(chēng)為生命周期。
1.新建狀態(tài)
使用 new Thread 類(lèi)或其子類(lèi)建立一個(gè)線程對(duì)象后,該線程對(duì)象就處于新建狀態(tài)。
2.就緒狀態(tài)
調(diào)用了start()方法之后,該線程就進(jìn)入就緒狀態(tài)(就緒隊(duì)列中),等待JVM里線程調(diào)度器的調(diào)度。
3.運(yùn)行狀態(tài)
執(zhí)行 run(),此時(shí)線程便處于運(yùn)行狀態(tài)。處于運(yùn)行狀態(tài)的線程最為復(fù)雜,它可以變?yōu)樽枞麪顟B(tài)、就緒狀態(tài)和死亡狀態(tài)。
4.阻塞狀態(tài)
如果一個(gè)線程執(zhí)行了sleep(睡眠)、suspend(掛起)等方法,失去所占用資源之后,該線程就從運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài)。
5.死亡狀態(tài)
一個(gè)運(yùn)行狀態(tài)的線程完成任務(wù)或者其他終止條件發(fā)生時(shí),該線程就切換到終止?fàn)顟B(tài)。
03
線程的調(diào)度策略
線程調(diào)度是指系統(tǒng)為線程分配處理器使用權(quán)的過(guò)程。
Java?使用的線程調(diào)度是搶占式調(diào)度,在搶占式調(diào)度下,優(yōu)先級(jí)最高的任務(wù)一直執(zhí)行,直到它進(jìn)入等待或死亡狀態(tài)或更高優(yōu)先級(jí)的任務(wù)出現(xiàn),優(yōu)先級(jí)高的線程比優(yōu)先級(jí)低的線程優(yōu)先執(zhí)行。
在Java多線程環(huán)境中,為保證所有線程的執(zhí)行能按照一定的規(guī)則執(zhí)行,JVM實(shí)現(xiàn)了一個(gè)線程調(diào)度器,它定義了線程調(diào)度的策略。 在?JVM?中體現(xiàn)為讓可運(yùn)行池中優(yōu)先級(jí)高的線程擁有CPU?使用權(quán)。
04
線程之間的通信與協(xié)作
上面比較清楚的顯示了線程的狀態(tài)流轉(zhuǎn),其實(shí)重點(diǎn)主要是掌握運(yùn)行、阻塞、就緒之間的通信機(jī)制。
1.sleep()和yield()和join()
1)sleep()方法作用:讓當(dāng)前線程睡眠一段時(shí)間,期間不會(huì)釋放任何持有的鎖。
2) yield()方法作用:讓出該線程的時(shí)間片給其它線程。線程調(diào)用了yield()方法,表示放棄當(dāng)前獲得的CPU時(shí)間片,回到就緒狀態(tài)。最后由線程調(diào)度重新選擇就緒狀態(tài)的線程分配CPU資源。
3)join()方法作用:暫停當(dāng)前線程,等待被調(diào)用線程指向結(jié)束之后再繼續(xù)執(zhí)行。
注意:
1)sleep(long)方法僅釋放CPU使用權(quán),鎖仍然占用。
2)調(diào)用join()的時(shí)候,當(dāng)前線程不會(huì)釋放掉鎖。
2.wait()和notify() 方法和notifyAll()方法
1)wait()方法的作用:讓該線程處于等待狀態(tài)。
2)notify()方法的作用:?jiǎn)拘烟幱趙ait的線程。
3)notifyAll()方法的作用:?jiǎn)拘阉刑幱趙ait狀態(tài)的線程。
注意:
1)wait()方法會(huì)釋放CPU執(zhí)行權(quán) 和 占有的鎖。
2) 線程調(diào)用wait()方法后,讓該線程處于等待狀態(tài)。進(jìn)入這個(gè)狀態(tài)后,是不能自動(dòng)喚醒的,必須依靠其他線程調(diào)用notify()或notifyAll()方法才能被喚醒。wait和notify必須配套使用,即必須使用同一把鎖調(diào)用。