我們知道線程是操作系統能夠進行運算調度的最小單位,在java中的線程其實就是對操作系統的中的線程進行了封裝。
我們今天就來說說Java線程的生命周期,也就線程的生老病死!
Java的線程生命周期有六種狀態:
-
New(初始化狀態)
-
Runnable(就緒狀態)
-
Running(運行狀態)
-
Blocked(阻塞狀態)
-
Terminated(終止狀態)
1.New(初始化狀態):當線程對象對創建后,即進入了新建狀態,如:Thread t = new MyThread();
2.Runnable(就緒狀態):當調用線程對象的start()方法,線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經做好了准備,隨時等待CPU調度執行,並不是說執行了start()此線程立即就會執行;
3.Running(運行狀態):當就緒狀態中的線程獲得了CUP執行資源,執行run()中的代碼,這樣的線程我們稱為運行狀態的線程。
4.Blocked(阻塞狀態):處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才有機會再次被CPU調用以進入到運行狀態。線程的阻塞狀態分為兩種:
第一種,Waiting(無時間限制的等待狀態):
這個狀態下是不能分配CPU執行的。有三種情況會使得Running狀態到waiting狀態
- 調用無參的Object.wait()方法。等到notifyAll()或者notify()喚醒就會回到Runnable狀態。
- 調用無參的Thread.join()方法。也就是比如你在主線程里面建立了一個線程A,調用A.join(),那么你的主線程是得等A執行完了才會繼續執行,這是你的主線程就是等待狀態。
- 調用LockSupport.park()方法。LockSupport是Java6引入的一個工具類Java並發包中的鎖都是基於它實現的,再調用LocakSupport.unpark(Thread thread),就會回到Runnable狀態。
第二種,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)。
5.Terminated(終止狀態):在我們的線程正常run結束之后或者run一半異常了就是終止狀態!
注意有個方法Thread.stop()是讓線程終止的,但是這個方法已經被廢棄了,不推薦使用,因為比如你這個線程得到了鎖,你stop了之后這個鎖也隨着沒了,其它線程就都拿不到這個鎖了!這不玩完了么!
所以推薦使用interrupt()方法。
interrupt()會使得線程Waiting和Timed_Waiting狀態的線程拋出 interruptedException異常,調用interrupt()方法后,使得Running狀態的線程再調用wait()、sleep()、jion()方法時拋出interruptedException異常,需要在catch中處理線程異常后的問題。
如果Running狀態的線程沒有阻塞在I/O狀態的話,那只能主動檢測自己是不是被中斷了,使用isInterrupted()。