咱們知道線程是操做系統可以進行運算調度的最小單位,在java中的線程其實就是對操做系統的中的線程進行了封裝。java
咱們今天就來講說Java線程的生命週期,也就線程的生老病死!面試
Java的線程生命週期有六種狀態:併發
New(初始化狀態)分佈式
Runnable(可運行/運行狀態)工具
Blocked(阻塞狀態)性能
Waiting(無時間限制的等待狀態)操作系統
Timed_Waiting(有時間限制的等待狀態)線程
Terminated(終止狀態)cdn
1.New(初始化狀態):指的是在高級語言,好比Java。在Java層面的線程被建立了,而在操做系統中的線程實際上是還沒被建立的,因此這個時候是不可能分配CPU執行這個線程的!因此這個狀態是高級語言獨有的,操做系統的線程沒這個狀態。咱們New了一個線程,那時候它就是這個狀態。blog
2.Runnable(可運行/運行狀態):這個狀態下是能夠分配CPU執行的,在New狀態時候咱們調用start()方法後線程就處於這個狀態。
3.Blocked(阻塞狀態): 這個狀態下是不能分配CPU執行的,只有一種狀況會致使線程阻塞,就是synchronized!咱們知道被synchronized修飾的方法或者代碼塊同一時刻只能有一個線程執行,而其餘競爭鎖的線程就從Runnable到了Blocked狀態!當某個線程競爭到鎖了它就變成了Runnable狀態。
注意併發包中的Lock,是會讓線程屬於等待狀態而不是阻塞,只有synchronized是阻塞。(感受是歷史遺留問題,不必多一個阻塞狀態和等待沒差啊)
4.Waiting(無時間限制的等待狀態): 這個狀態下也是不能分配CPU執行的。有三種狀況會使得Runnable狀態到waiting狀態
1.調用無參的Object.wait()方法。等到notifyAll()或者notify()喚醒就會回到Runnable狀態。
2.調用無參的Thread.join()方法。也就是好比你在主線程裏面創建了一個線程A,調用A.join(),那麼你的主線程是得等A執行完了纔會繼續執行,這是你的主線程就是等待狀態。
3.調用LockSupport.park()方法。LockSupport是Java6引入的一個工具類Java併發包中的鎖都是基於它實現的,再調用LocakSupport.unpark(Thread thread),就會回到Runnable狀態。
5.Timed_Waiting(有時間限制的等待狀態): 其實這個狀態和Waiting就是有沒有超時時間的差異,這個狀態下也是不能分配CPU執行的。有五種狀況會使得Runnable狀態到waiting狀態。
Object.wait(long timeout)。
Thread.join(long millis)。
Thread.sleep(long millis)。注意Thread.sleep(long millis, int nanos) 內部調用的其實也是Thread.sleep(long millis)。
LockSupport.parkNanos(Object blocked,long deadline)。
LockSupport.parkUntil(long deadline)。
6.Terminated(終止狀態): 在咱們的線程正常run結束以後或者run一半異常了就是終止狀態!
注意有個方法Thread.stop()是讓線程終止的,可是這個方法已經被廢棄了,不推薦使用,由於好比你這個線程獲得了鎖,你stop了以後這個鎖也隨着沒了,其它線程就都拿不到這個鎖了!這不玩完了麼!因此推薦使用interrupt()方法。
interrupt()會使得線程Waiting和Timed_Waiting狀態的線程拋出 interruptedException異常,使得Runnabled狀態的線程若是是在I/O操做會拋出其它異常。
若是Runnabled狀態的線程沒有阻塞在I/O狀態的話,那隻能主動檢測本身是否是被中斷了,使用isInterrupted()。
若有錯誤歡迎指正!
我的公衆號:yes的練級攻略
有相關面試進階(分佈式、性能調優、經典書籍pdf)資料等待領取