線程間的狀態轉換說明:jvm
new
):新建立了一個線程對象。runnable
):線程對象建立後,其餘線程(好比main線程
)調用了該對象的start()
方法。該狀態的線程位於可運行線程池中,等待被線程調度選中,獲取cpu
的使用權 。running
):可運行狀態(runnable
)的線程得到了cpu
時間片(timeslice
) ,執行程序代碼。阻塞狀態(blocked
):阻塞狀態是指線程由於某種緣由放棄了cpu使用權
,也即讓出了cpu timeslice
,暫時中止運行。直到線程進入可運行(runnable
)狀態,纔有機會再次得到cpu timeslice
轉到運行(running
)狀態。阻塞的狀況分三種:spa
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是不會釋放持有的鎖
)。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()
方法來判斷和設置一個線程是否爲後臺線程
。線程類的一些經常使用方法:線程
非守護線程
(用戶線程)執行完畢後退出;用戶線程
;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()); } } }