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