摘要:死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。直到當(dāng)前的線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程。枚舉程序中的線程。強(qiáng)迫一個(gè)線程等待。通知一個(gè)線程繼續(xù)運(yùn)行。
一. 線程狀態(tài)轉(zhuǎn)換圖
線程間的狀態(tài)轉(zhuǎn)換說(shuō)明:
新建(new):新創(chuàng)建了一個(gè)線程對(duì)象。
可運(yùn)行狀態(tài)(runnable):線程對(duì)象創(chuàng)建后,其他線程(比如main線程)調(diào)用了該對(duì)象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中,等待被線程調(diào)度選中,獲取cpu的使用權(quán) 。
運(yùn)行(running):可運(yùn)行狀態(tài)(runnable)的線程獲得了cpu時(shí)間片(timeslice) ,執(zhí)行程序代碼。
阻塞狀態(tài)(blocked):阻塞狀態(tài)是指線程因?yàn)槟撤N原因放棄了cpu使用權(quán),也即讓出了cpu timeslice,暫時(shí)停止運(yùn)行。直到線程進(jìn)入可運(yùn)行(runnable)狀態(tài),才有機(jī)會(huì)再次獲得cpu timeslice 轉(zhuǎn)到運(yùn)行(running)狀態(tài)。阻塞的情況分三種:
等待阻塞:運(yùn)行(running)的線程執(zhí)行o.wait()方法,JVM會(huì)把該線程放入等待隊(duì)列(waitting queue)中(wait會(huì)釋放持有的鎖)。
同步阻塞:運(yùn)行(running)的線程在獲取對(duì)象的同步鎖時(shí),若該同步鎖被別的線程占用,則JVM會(huì)把該線程放入鎖池(lock pool)中。
其他阻塞:運(yùn)行(running)的線程執(zhí)行Thread.sleep(long ms)或t.join()方法,或者發(fā)出了I/O請(qǐng)求時(shí),JVM會(huì)把該線程置為阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí)或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入可運(yùn)行(runnable)狀態(tài)(注意:sleep是不會(huì)釋放持有的鎖)。
死亡(dead):線程run()、main()方法執(zhí)行結(jié)束,或者因異常退出了run()方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。
二. 線程的調(diào)度調(diào)整線程優(yōu)先級(jí):Java線程有優(yōu)先級(jí),優(yōu)先級(jí)高的線程會(huì)獲得較多的運(yùn)行機(jī)會(huì)。
線程睡眠:Thread.sleep(long millis)方法,使線程轉(zhuǎn)到阻塞狀態(tài)。millis參數(shù)設(shè)定睡眠的時(shí)間,以毫秒為單位。當(dāng)睡眠結(jié)束后,就轉(zhuǎn)為就緒(Runnable)狀態(tài)。sleep()平臺(tái)移植性好。
線程等待:Object類中的wait()方法,導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify()方法或notifyAll()喚醒方法。這個(gè)兩個(gè)喚醒方法也是Object類中的方法,行為等價(jià)于調(diào)用 wait(0)。
線程讓步:Thread.yield()方法,暫停當(dāng)前正在執(zhí)行的線程對(duì)象,把執(zhí)行機(jī)會(huì)讓給相同或者更高優(yōu)先級(jí)的線程。
線程加入:join()方法,等待其他線程終止。在當(dāng)前線程中調(diào)用另一個(gè)線程的join()方法,則當(dāng)前線程轉(zhuǎn)入阻塞狀態(tài),直到另一個(gè)進(jìn)程運(yùn)行結(jié)束,當(dāng)前線程再由阻塞轉(zhuǎn)為就緒狀態(tài)。
線程喚醒:Object類中的notify()方法,喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。如果所有線程都在此對(duì)象上等待,則會(huì)選擇喚醒其中一個(gè)線程。選擇是任意性的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程通過(guò)調(diào)用其中一個(gè)wait方法,在對(duì)象的監(jiān)視器上等待。直到當(dāng)前的線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程。被喚醒的線程將以常規(guī)方式與在該對(duì)象上主動(dòng)同步的其他所有線程進(jìn)行競(jìng)爭(zhēng);例如,喚醒的線程在作為鎖定此對(duì)象的下一個(gè)線程方面沒有可靠的特權(quán)或劣勢(shì)。類似的方法還有一個(gè)notifyAll(),喚醒在此對(duì)象監(jiān)視器上等待的所有線程。
注意:Thread中suspend()和resume()兩個(gè)方法在JDK1.5中已經(jīng)廢除,不再介紹。因?yàn)橛兴梨i傾向。三. 常見線程名詞解釋
主線程:JVM調(diào)用程序main()所產(chǎn)生的線程。
當(dāng)前線程:這個(gè)是容易混淆的概念。一般指通過(guò)Thread.currentThread()來(lái)獲取的進(jìn)程。
后臺(tái)線程:指為其他線程提供服務(wù)的線程,也稱為守護(hù)線程。JVM的垃圾回收線程就是一個(gè)后臺(tái)線程。用戶線程和守護(hù)線程的區(qū)別在于,守護(hù)線程等待用戶線程結(jié)束而結(jié)束
前臺(tái)線程:是指接受后臺(tái)線程服務(wù)的線程,其實(shí)前臺(tái)后臺(tái)線程是聯(lián)系在一起,就像傀儡和幕后操縱者一樣的關(guān)系。傀儡是前臺(tái)線程、幕后操縱者是后臺(tái)線程。由前臺(tái)線程創(chuàng)建的線程默認(rèn)也是前臺(tái)線程。可以通過(guò)isDaemon()和setDaemon()方法來(lái)判斷和設(shè)置一個(gè)線程是否為后臺(tái)線程。
線程類的一些常用方法:
sleep(): 強(qiáng)迫一個(gè)線程睡眠N毫秒。
isAlive(): 判斷一個(gè)線程是否存活。
join(): 等待線程終止。
activeCount(): 程序中活躍的線程數(shù)。
enumerate(): 枚舉程序中的線程。
currentThread(): 得到當(dāng)前線程。
isDaemon(): 一個(gè)線程是否為守護(hù)線程。
setDaemon(): 設(shè)置一個(gè)線程為守護(hù)線程。
setName(): 為線程設(shè)置一個(gè)名稱。
wait(): 強(qiáng)迫一個(gè)線程等待。
notify(): 通知一個(gè)線程繼續(xù)運(yùn)行。
setPriority(): 設(shè)置一個(gè)線程的優(yōu)先級(jí)。
四. 關(guān)于main線程JVM會(huì)在所有的非守護(hù)線程(用戶線程)執(zhí)行完畢后退出;
main線程是用戶線程;
僅有main線程一個(gè)用戶線程執(zhí)行完畢,不能決定JVM是否退出,也即是說(shuō)main線程并不一定是最后一個(gè)退出的線程。
通過(guò)jstack我們可以把jvm當(dāng)前的線程狀態(tài)dump下來(lái)進(jìn)行分析驗(yàn)證
或者通過(guò)JMX的API進(jìn)行線程信息的輸出,代碼如下:
public class ThreadNumDemo { public static void main(String[] args) { ThreadMXBean threadMXBean =ManagementFactory.getThreadMXBean(); ThreadInfo[] threadInfos=threadMXBean.dumpAllThreads(false,false); for (ThreadInfo threadInfo : threadInfos) { System.out.println(threadInfo.getThreadId()+"-"+threadInfo.getThreadName()); } } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/69486.html
摘要:線程線程是進(jìn)程中的一個(gè)實(shí)體,作為系統(tǒng)調(diào)度和分派的基本單位。下的線程看作輕量級(jí)進(jìn)程。因此,使用的目的是讓相同優(yōu)先級(jí)的線程之間能適當(dāng)?shù)妮嗈D(zhuǎn)執(zhí)行。需要注意的是,是線程自己從內(nèi)部拋出的,并不是方法拋出的。 本文及后續(xù)相關(guān)文章梳理一下關(guān)于多線程和同步鎖的知識(shí),平時(shí)只是應(yīng)用層面的了解,由于最近面試總是問(wèn)一些原理性的知識(shí),雖說(shuō)比較反感這種理論派,但是為了生計(jì)也必須掌握一番。(PS:并不是說(shuō)掌握原理不...
摘要:線程同步方法是通過(guò)鎖來(lái)實(shí)現(xiàn),每個(gè)對(duì)象都有切僅有一個(gè)鎖,這個(gè)鎖與一個(gè)特定的對(duì)象關(guān)聯(lián),線程一旦獲取了對(duì)象鎖,其他訪問(wèn)該對(duì)象的線程就無(wú)法再訪問(wèn)該對(duì)象的其他非同步方法對(duì)于靜態(tài)同步方法,鎖是針對(duì)這個(gè)類的,鎖對(duì)象是該類的對(duì)象。 對(duì)實(shí)現(xiàn)了Runnable或者Callable接口類,可以通過(guò)多線程執(zhí)行同一實(shí)例的run或call方法,那么對(duì)于同一實(shí)例中的局部變量(非方法變量)就會(huì)有多個(gè)線程進(jìn)行更改或讀取...
摘要:所以接下來(lái),我們需要簡(jiǎn)單的介紹下多線程中的并發(fā)通信模型。比如中,以及各種鎖機(jī)制,均為了解決線程間公共狀態(tài)的串行訪問(wèn)問(wèn)題。 并發(fā)的學(xué)習(xí)門檻較高,相較單純的羅列并發(fā)編程 API 的枯燥被動(dòng)學(xué)習(xí)方式,本系列文章試圖用一個(gè)簡(jiǎn)單的栗子,一步步結(jié)合并發(fā)編程的相關(guān)知識(shí)分析舊有實(shí)現(xiàn)的不足,再實(shí)現(xiàn)邏輯進(jìn)行分析改進(jìn),試圖展示例子背后的并發(fā)工具與實(shí)現(xiàn)原理。 本文是本系列的第一篇文章,提出了一個(gè)簡(jiǎn)單的業(yè)務(wù)場(chǎng)景...
摘要:多線程編程就像一個(gè)沼澤,中間遍布各種各樣的陷阱。但是在多線程編程或者說(shuō)是并發(fā)編程中,有非常多的陷阱被埋在底層細(xì)節(jié)當(dāng)中。線程池類中用于控制線程池狀態(tài)和線程數(shù)的控制變量就是一個(gè)類型的字段。 多線程編程就像一個(gè)沼澤,中間遍布各種各樣的陷阱。大多數(shù)開發(fā)者絕大部分時(shí)間都是在做上層應(yīng)用的開發(fā),并不需要過(guò)多地涉入底層細(xì)節(jié)。但是在多線程編程或者說(shuō)是并發(fā)編程中,有非常多的陷阱被埋在底層細(xì)節(jié)當(dāng)中。如果不知...
摘要:線程啟動(dòng)規(guī)則對(duì)象的方法先行發(fā)生于此線程的每一個(gè)動(dòng)作。所以局部變量是不被多個(gè)線程所共享的,也就不會(huì)出現(xiàn)并發(fā)問(wèn)題。通過(guò)獲取到數(shù)據(jù),放入當(dāng)前線程處理完之后將當(dāng)前線程中的信息移除。主線程必須在啟動(dòng)其他線程后立即調(diào)用方法。 一、線程安全性 定義:當(dāng)多個(gè)線程訪問(wèn)某個(gè)類時(shí),不管運(yùn)行時(shí)環(huán)境采用何種調(diào)度方式,或者這些線程將如何交替執(zhí)行,并且在主調(diào)代碼中不需要任何額外的同步或協(xié)同,這個(gè)類都能表現(xiàn)出正確的行...
閱讀 1625·2023-04-26 01:36
閱讀 2793·2021-10-08 10:05
閱讀 2837·2021-08-05 09:57
閱讀 1591·2019-08-30 15:52
閱讀 1254·2019-08-30 14:12
閱讀 1379·2019-08-30 11:17
閱讀 3186·2019-08-29 13:07
閱讀 2507·2019-08-29 12:35