Java線程生命周期及轉(zhuǎn)換過程
前言:
線程的生命周期指的是線程從創(chuàng)建到銷毀的整個過程,通常情況下線程的生命周期有以下 5 種:
- 初始狀態(tài)
- 可運行狀態(tài)
- 運行狀態(tài)
- 休眠狀態(tài)
- 終止狀態(tài)
它們的狀態(tài)轉(zhuǎn)換如下圖所示:
Java 線程生命周期
Java 線程的生命周期和上面說的生命周期是不同的,它有以下 6 種狀態(tài):
- NEW(初始化狀態(tài))
- RUNNABLE(可運行/運行狀態(tài))
- BLOCKED(阻塞狀態(tài))
- WAITING(無時限等待狀態(tài))
- TIMED_WAITING(有時限等待狀態(tài))
- TERMINATED(終止狀態(tài))
我們可以在 Thread 的源碼中可以找到這 6 種狀態(tài),如下所示:
當然你也可以使用 Java 代碼,來打印所有的線程狀態(tài),如下代碼所示:
for (Thread.State value : Thread.State.values()) { System.out.println(value); }
以上程序的執(zhí)行結(jié)果如下圖所示:
生命周期轉(zhuǎn)換
接下來我們聊聊 Java 線程生命周期的轉(zhuǎn)換過程。
1.從 NEW 到 RUNNABLE
當我們創(chuàng)建一個線程的時候,也就是 new Thread 的時候,此時線程是 NEW 狀態(tài),如下代碼所示:
// 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { // ... } }); // 獲取線程狀態(tài) Thread.State state = thread.getState(); System.out.println(state);
以上程序的執(zhí)行結(jié)果如下圖所示:
然而調(diào)用了線程的 start 方法之后,線程的狀態(tài)就從 NEW 變成了 RUNNABLE,
如下代碼所示:
// 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { // 獲取到當前執(zhí)行的線程 Thread currThread = Thread.currentThread(); // 獲取線程狀態(tài) Thread.State state = currThread.getState(); // 打印線程狀態(tài) System.out.println(state); } }); thread.start();
以上程序的執(zhí)行結(jié)果如下圖所示:
2.從 RUNNABLE 到 BLOCKED
當線程中的代碼排隊執(zhí)行 synchronized 時,線程就會從 RUNNABLE 狀態(tài)變?yōu)?BLOCKED 阻塞狀態(tài)
如下代碼所示:
// 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { try { // 等待 100 毫秒 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("排隊使用鎖"); synchronized (ThreadStates.class) { } } }); thread.start(); // 讓主線程先得到鎖 synchronized (ThreadStates.class) { // 獲取線程狀態(tài) Thread.State state = thread.getState(); // 打印線程狀態(tài) System.out.println("首次獲取線程狀態(tài):" + state); // 休眠 1s try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 再次獲取線程狀態(tài) state = thread.getState(); // 打印線程狀態(tài) System.out.println("第二次獲取線程狀態(tài):" + state); }
以上程序的執(zhí)行結(jié)果如下圖所示:
當線程獲取到 synchronized 鎖之后,就會從 BLOCKED 狀態(tài)轉(zhuǎn)變?yōu)?RUNNABLE 狀態(tài)。
3.從 RUNNABLE 到 WAITTING
線程調(diào)用 wait() 方法之后,就會從 RUNNABLE 狀態(tài)變?yōu)?WAITING 無時限等待狀態(tài),如下所示:
// 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { synchronized (this) { try { // 線程休眠 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }); // 啟動線程 thread.start(); // 獲取線程狀態(tài) Thread.State state = thread.getState(); // 打印線程狀態(tài) System.out.println("首次獲取線程狀態(tài):" + state); // 休眠 1s try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 獲取線程狀態(tài) state = thread.getState(); // 打印線程狀態(tài) System.out.println("第二次獲取線程狀態(tài):" + state);
以上程序的執(zhí)行結(jié)果如下圖所示:
當調(diào)用了 notify/notifyAll 方法之后,線程會從 WAITING 狀態(tài)變成 RUNNABLE 狀態(tài),
如下代碼所示:
Object lock = new Object(); // 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { try { // 線程休眠 lock.wait(); // 獲取當前線程狀態(tài) Thread.State state = Thread.currentThread().getState(); // 打印線程狀態(tài) System.out.println("獲取線程狀態(tài):" + state); } catch (InterruptedException e) { e.printStackTrace(); } } } }); // 啟動線程 thread.start(); // 獲取線程狀態(tài) Thread.State state = thread.getState(); // 打印線程狀態(tài) System.out.println("首次獲取線程狀態(tài):" + state); // 休眠 1s try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 獲取線程狀態(tài) state = thread.getState(); // 打印線程狀態(tài) System.out.println("第二次獲取線程狀態(tài):" + state); // 喚醒 thread 線程 synchronized (lock) { lock.notify(); }
以上程序的執(zhí)行結(jié)果如下圖所示:
4.從 RUNNABLE 到 TIMED_WATTING
當調(diào)用帶超時時間的等待方法時,如 sleep(xxx),線程會從 RUNNABLE 狀態(tài)變成 TIMED_WAITING 有時限狀態(tài),
如下代碼所示:
// 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); // 啟動線程 thread.start(); // 獲取線程狀態(tài) Thread.State state = thread.getState(); // 打印線程狀態(tài) System.out.println("首次獲取線程狀態(tài):" + state); // 休眠 1s try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 獲取線程狀態(tài) state = thread.getState(); // 打印線程狀態(tài) System.out.println("第二次獲取線程狀態(tài):" + state);
以上程序的執(zhí)行結(jié)果如下圖所示:
當超過了超時時間之后,線程就會從 TIMED_WAITING 狀態(tài)變成 RUNNABLE 狀態(tài),
實現(xiàn)代碼如下:
// 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); // 獲取當前線程狀態(tài) Thread.State state = Thread.currentThread().getState(); // 打印線程狀態(tài) System.out.println("獲取線程狀態(tài):" + state); } catch (InterruptedException e) { e.printStackTrace(); } } }); // 啟動線程 thread.start(); // 獲取線程狀態(tài) Thread.State state = thread.getState(); // 打印線程狀態(tài) System.out.println("首次獲取線程狀態(tài):" + state); // 休眠 1s try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 獲取線程狀態(tài) state = thread.getState(); // 打印線程狀態(tài) System.out.println("第二次獲取線程狀態(tài):" + state);
以上程序的執(zhí)行結(jié)果如下圖所示:
5.RUNNABLE 到 TERMINATED
線程執(zhí)行完之后,就會從 RUNNABLE 狀態(tài)變成 TERMINATED 銷毀狀態(tài),如下代碼所示:
// 創(chuàng)建線程 Thread thread = new Thread(new Runnable() { @Override public void run() { // 獲取當前線程狀態(tài) Thread.State state = Thread.currentThread().getState(); // 打印線程狀態(tài) System.out.println("獲取線程狀態(tài):" + state); } }); // 啟動線程 thread.start(); // 等待 100ms,待線程執(zhí)行完 Thread.sleep(100); // 獲取線程狀態(tài) Thread.State state = thread.getState(); // 打印線程狀態(tài) System.out.println("線程狀態(tài):" + state);
以上程序的執(zhí)行結(jié)果如下圖所示:
總結(jié)
Java 中線程的生命周期有 6 種:NEW(初始化狀態(tài))、RUNNABLE(可運行/運行狀態(tài))、BLOCKED(阻塞狀態(tài))、WAITING(無時限等待狀態(tài))、TIMED_WAITING(有時限等待狀態(tài))、TERMINATED(終止狀態(tài))。
線程生命周期的轉(zhuǎn)換流程如下圖所示:
到此這篇關(guān)于Java線程生命周期及轉(zhuǎn)換過程的文章就介紹到這了,更多相關(guān)Java線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring+SpringMVC+MyBatis深入學(xué)習(xí)及搭建(二)之MyBatis原始Dao開發(fā)和mapper代理開發(fā)
這篇文章主要介紹了Spring+SpringMVC+MyBatis深入學(xué)習(xí)及搭建(二)之MyBatis原始Dao開發(fā)和mapper代理開發(fā),需要的朋友可以參考下2017-05-05MyBatis-Plus工具使用之EntityWrapper解析
這篇文章主要介紹了MyBatis-Plus工具使用之EntityWrapper解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03