什么是多線程 提到線程,,不得不先說一下什么是進(jìn)程,。 進(jìn)程就是正在運(yùn)行的程序。當(dāng)一個(gè)程序進(jìn)入內(nèi)存運(yùn)行時(shí),,即變成一個(gè)進(jìn)程,。每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文)。一個(gè)進(jìn)程包含1--n個(gè)線程,。一個(gè)線程不能獨(dú)立的存在,,它必須是進(jìn)程的一部分。 線程是進(jìn)程的組成部分,,一個(gè)進(jìn)程可以有多個(gè)線程,,但一個(gè)線程必須只有一個(gè)父進(jìn)程。線程可以擁有自己的棧,,自己的程序計(jì)數(shù)器和自己的局部變量,,但不擁有父進(jìn)程資源,處理資源一般是父進(jìn)程把資源(對象指針)傳給線程,,它與父進(jìn)程的其他線程共享該進(jìn)程所擁有的全部資源,。 多線程就是同一進(jìn)程可以同時(shí)并發(fā)處理多個(gè)線程,它們獨(dú)立運(yùn)行,,互不妨礙,。多線程能滿足程序員編寫高效率的程序來達(dá)到充分利用CPU的目的。
一個(gè)線程的生命周期 線程是一個(gè)動態(tài)執(zhí)行的過程,,它也有一個(gè)從產(chǎn)生到死亡的過程,。下圖顯示了一個(gè)線程完整的生命周期。
下面是對其中名詞的解釋: 新建狀態(tài)(New):新創(chuàng)建了一個(gè)線程對象,。 就緒狀態(tài)(Runnable):線程對象創(chuàng)建后,,其他線程調(diào)用了該對象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中,,變得可運(yùn)行,,等待獲取CPU的使用權(quán)。 運(yùn)行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,,執(zhí)行程序代碼,。 阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán),暫時(shí)停止運(yùn)行,。直到線程進(jìn)入就緒狀態(tài),,才有機(jī)會轉(zhuǎn)到運(yùn)行狀態(tài)。阻塞的情況分三種: (1)等待阻塞:運(yùn)行的線程執(zhí)行wait()方法,,JVM會把該線程放入等待池中,。(wait會釋放持有的鎖) (2)同步阻塞:運(yùn)行的線程在獲取對象的同步鎖時(shí),若該同步鎖被別的線程占用,,則JVM會把該線程放入鎖池中,。 (3)其他阻塞:運(yùn)行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請求時(shí),,JVM會把該線程置為阻塞狀態(tài),。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí),、或者I/O處理完畢時(shí),,線程重新轉(zhuǎn)入就緒狀態(tài)。 死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,,該線程結(jié)束生命周期,。 線程睡眠(sleep()):Thread.sleep(long millis)方法,使線程轉(zhuǎn)到阻塞狀態(tài),。millis參數(shù)設(shè)定睡眠的時(shí)間,,以毫秒為單位。當(dāng)睡眠結(jié)束后,,就轉(zhuǎn)為就緒(Runnable)狀態(tài),。sleep()平臺移植性。注意,sleep是不會釋放持有的鎖,。 線程加入(join()):執(zhí)行threadObj.join()方法,,父線程(主線程)會等到threadObj運(yùn)行終止后再執(zhí)行。在當(dāng)前線程(主線程)中調(diào)用另一個(gè)線程(子線程)的join()方法,,則當(dāng)前線程轉(zhuǎn)入阻塞狀態(tài),,直到另一個(gè)線程運(yùn)行結(jié)束,當(dāng)前線程再由阻塞轉(zhuǎn)為就緒狀態(tài),。也就是主線程中,,子線程調(diào)用了join()方法后面的代碼,只有等到子線程結(jié)束了才能執(zhí)行,。 線程讓步(yield()):Thread.yield()方法,,暫停當(dāng)前正在執(zhí)行的線程對象,把執(zhí)行機(jī)會讓給相同或者更高優(yōu)先級的線程,。yield()讓當(dāng)前運(yùn)行線程回到可運(yùn)行狀態(tài),,以允許具有相同優(yōu)先級的其他線程獲得運(yùn)行機(jī)會。因此,,使用yield()的目的是讓相同優(yōu)先級的線程之間能適當(dāng)?shù)妮嗈D(zhuǎn)執(zhí)行,。但是,實(shí)際中無法保證yield()達(dá)到讓步目的,因?yàn)樽尣降木€程還有可能被線程調(diào)度程序再次選中,。 線程等待/線程喚醒:Object類中的wait()方法,,導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對象的notify()方法或notifyAll()喚醒方法,。要注意的是: (1)obj.wait(),,與obj.notify()必須要與synchronized(obj)一起使用,也就是wait與notify是針對已經(jīng)獲取了obj鎖進(jìn)行操作,,從語法角度來說就是obj.wait(),obj.notify()必須在synchronized(obj){...}語句塊內(nèi),。 (2)當(dāng)線程執(zhí)行wait()時(shí),會把當(dāng)前的鎖釋放,,然后讓出CPU,,進(jìn)入等待狀態(tài)。 (3)當(dāng)執(zhí)行notify()/notifyAll()方法時(shí),,會喚醒一個(gè)處于等待該對象鎖的線程,,然后繼續(xù)往下執(zhí)行,直到執(zhí)行完退出對象鎖鎖住的區(qū)域(synchronized修飾的代碼塊)后再釋放鎖,。
|
|