日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java多线程 —— 线程状态迁移

發(fā)布時(shí)間:2025/3/12 java 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java多线程 —— 线程状态迁移 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引言

線程狀態(tài)遷移,又常被稱作線程的生命周期,指的是線程從創(chuàng)建到終結(jié)需要經(jīng)歷哪些狀態(tài),什么情況下會(huì)出現(xiàn)哪些狀態(tài)。

線程的狀態(tài)直接關(guān)系著并發(fā)編程的各種問(wèn)題,本文就線程的狀態(tài)遷移做一初步探討,并總結(jié)在何種情況下會(huì)出現(xiàn)這些狀態(tài),嘗試將這些狀態(tài)通過(guò)一些程序模擬出來(lái)。

一、六種狀態(tài)

java.lang.Thread 的狀態(tài)分為以下 6 種,它們以枚舉的形式,封裝在了Thread類內(nèi)部:

NEW:表示線程剛剛創(chuàng)建出來(lái),還未啟動(dòng)

RUNNABLE:可運(yùn)行狀態(tài),該狀態(tài)的線程可以是ready或running,唯一的決定因素是線程調(diào)度器

BLOCKED:阻塞,線程正在等待一個(gè)monitor鎖以便進(jìn)入一個(gè)同步代碼塊

WAITING:等待,一種掛起等待的狀態(tài)。一個(gè)線程處于waiting是為了等待其他線程執(zhí)行某個(gè)特定的動(dòng)作。

TIMED_WAITING:定時(shí)等待。

TERMINATED:終結(jié),線程執(zhí)行結(jié)束后的狀態(tài)。

二、狀態(tài)遷移圖

線程遷移圖網(wǎng)上有很多,這是我自己參考著繪制的一張。

線程遷移圖雖然是背了忘忘了背,反反復(fù)復(fù)很多遍,但是記憶這張圖其實(shí)并不困難。首先就是NEW和TERMINATED狀態(tài),一個(gè)表示剛剛創(chuàng)建,一個(gè)表示任務(wù)結(jié)束。

最重要的是記住WAITING和BLOCKED這兩種狀態(tài)與RUNNABLE相互切換的條件。

BLOCKED狀態(tài)在Java doc中的描述是“等待一個(gè)monitor鎖”,monitor對(duì)象是與對(duì)象實(shí)例相關(guān)聯(lián)的一個(gè)鎖對(duì)象,這個(gè)鎖對(duì)象實(shí)際上就是 synchronized 的具體實(shí)現(xiàn),一般稱之為重量級(jí)鎖,進(jìn)入同步代碼塊的過(guò)程,實(shí)際上就是獲取到 monitor 對(duì)象的鎖的過(guò)程。如果鎖被其他線程占用,當(dāng)前線程就變成了BLOCKED狀態(tài),如果得到了鎖,就由BLOCKED切換到RUNNABLE狀態(tài)。

WAITING 是一種掛起狀態(tài),處于 waiting 的線程表示它正在等待一個(gè)有緣人~ 這個(gè)有緣人需要執(zhí)行特定的動(dòng)作才能解救 waiting 中的線程。就像孫悟空在五指山下等了五百年,只有玄奘摘下山頂?shù)姆洳拍軌蚱仆炼觥?/p>

導(dǎo)致 WAITING 的情況只有三種:

wait()

join()

LockSupport.park()

wait() 方法是 Object 的成員方法,它可以令當(dāng)前線程針對(duì)于某個(gè)對(duì)象掛起等待,并釋放獲得的鎖資源,只有當(dāng)其他線程調(diào)用這個(gè)對(duì)象的notify()或 notifyAll() 方法,才能夠喚醒等待中的線程。注意,notify()或 notifyAll() 不會(huì)釋放鎖資源。

join() 方法是線程的一個(gè)成員方法,“加入一個(gè)線程”,這好像合情合理,比如 t1線程在執(zhí)行的過(guò)程中調(diào)用了 t2.join(),那么好吧, t1就會(huì)由 RUNNABLE 變?yōu)?WAITING,因?yàn)樗却?t2 執(zhí)行完后才會(huì)繼續(xù)執(zhí)行,說(shuō)白了,就是方便程序員讓線程插隊(duì)用的:

LockSupport.park()更方便,它是一個(gè)靜態(tài)方法,可以讓線程在調(diào)用的位置直接WAITING,然后在其他線程中,獲取到WAITING中的線程對(duì)象,傳入LockSupport(thread) 直接恢復(fù)運(yùn)行。

三、線程狀態(tài)模擬

準(zhǔn)備三個(gè)線程 monitor 監(jiān)視線程,主要實(shí)時(shí)監(jiān)視 t1線程的狀態(tài);

t1 線程模擬各種狀態(tài),t2 輔助 t1 模擬各種狀態(tài):

public class ThreadState {static Object lock = new Object();// 模擬 NEW、RUNNABLE、WAITING、TIMED_WAITING、BLOCKED、TERMINATEDpublic static void main(String[] args) {ThreadState thisObj = new ThreadState();Thread t1 = new Thread(() -> {try {// 先獲取 t2 對(duì)象Thread t2 = getThreadByName("t2");// 先執(zhí)行一套邏輯,推遲同步代碼塊的調(diào)用String str = "";for (int i = 0; i < 10000; i++) {str += i;}// 調(diào)用同步代碼塊thisObj.doSync();// t2準(zhǔn)備插隊(duì)t2.join();} catch (InterruptedException e) {e.printStackTrace();}}, "t1");System.out.println("t1 剛創(chuàng)建:" + t1.getState());Thread t2 = new Thread(() -> {try {// 直接獲取同步鎖thisObj.doSync();// 釋放鎖后在運(yùn)行一段時(shí)間TimeUnit.SECONDS.sleep(30);} catch (Exception e) {e.printStackTrace();}}, "t2");Thread monitor = new Thread(() -> {Thread.State t1State = null;while (true) {if (!t1.getState().equals(t1State)) {t1State = t1.getState();System.out.println("t1 此刻狀態(tài):" + t1.getState());}if (t1State.equals(Thread.State.TERMINATED))break;}}, "monitor");monitor.start();t2.start();t1.start();}public synchronized void doSync() {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}String str = "";for (int i = 0; i < 100000; i++) {str += i;}}public static Thread getThreadByName(String name) {Optional<Thread> first = Thread.getAllStackTraces().keySet().stream().filter(thread -> thread.getName().equals(name)).findFirst();return first.get();} }

輸出:

t1 剛創(chuàng)建:NEW t1 此刻狀態(tài):RUNNABLE t1 此刻狀態(tài):BLOCKED t1 此刻狀態(tài):TIMED_WAITING t1 此刻狀態(tài):TIMED_WAITING t1 此刻狀態(tài):RUNNABLE t1 此刻狀態(tài):WAITING t1 此刻狀態(tài):BLOCKED t1 此刻狀態(tài):TERMINATED

總結(jié)

線程狀態(tài)遷移是非常重要的多線程基礎(chǔ)知識(shí),在調(diào)試多線程問(wèn)題的時(shí)候,能夠發(fā)揮很大的作用。

6 種狀態(tài)不僅要熟記,而且在什么情況下會(huì)出現(xiàn)這些狀態(tài)也要清晰明了。

如果條件允許,可以試著通過(guò)不同的方法來(lái)模擬線程的六種狀態(tài)的切換,可以加深對(duì)線程生命周期的理解。

?

?

總結(jié)

以上是生活随笔為你收集整理的Java多线程 —— 线程状态迁移的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。