电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Java中Thread.join()的使用方法

瀏覽:12日期:2022-08-27 16:58:16

概要

本文分三個部分對Thread.join()進行分析:

1. join() 的示例和作用

2. join() 源碼分析

3. 對網上其他分析 join() 的文章提出疑問

1. join() 的示例和作用

1.1 示例

// 父線程public class Parent { public static void main(String[] args) { // 創建child對象,此時child表示的線程處于NEW狀態 Child child = new Child(); // child表示的線程轉換為RUNNABLE狀態 child.start(); // 等待child線程運行完再繼續運行 child.join(); }}

// 子線程public class Child extends Thread { public void run() { // ... }}

上面代碼展示了兩個類:Parent(父線程類),Child(子線程類)。

Parent.main()方法是程序的入口,通過Child child = new Child(); 新建child子線程(此時 child子線程處于NEW狀態);

然后調用child.start()(child子線程狀態轉換為RUNNABLE);

再調用child.join(),此時,Parent父線程會等待child子線程運行完再繼續運行。

下圖是我總結的 Java 線程狀態轉換圖:

Java中Thread.join()的使用方法

1.2 join() 的作用

讓父線程等待子線程結束之后才能繼續運行。

我們來看看在 Java 7 Concurrency Cookbook 中相關的描述(很清楚地說明了 join() 的作用):

Waiting for the finalization of a thread

In some situations, we will have to wait for the finalization of a thread. For example, we mayhave a program that will begin initializing the resources it needs before proceeding with therest of the execution. We can run the initialization tasks as threads and wait for its finalizationbefore continuing with the rest of the program.For this purpose, we can use the join() method of the Thread class. When we call thismethod using a thread object, it suspends the execution of the calling thread until the objectcalled finishes its execution.

當我們調用某個線程的這個方法時,這個方法會掛起調用線程,直到被調用線程結束執行,調用線程才會繼續執行。

2. join() 源碼分析

以下是 JDK 8 中 join() 的源碼:

public final void join() throws InterruptedException { join(0);}public final synchronized void join(long millis)throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException('timeout value is negative'); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } }}public final synchronized void join(long millis, int nanos)throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException('timeout value is negative'); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( 'nanosecond timeout value out of range'); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } join(millis);}

join() 一共有三個重載版本,分別是無參、一個參數、兩個參數:

public final void join() throws InterruptedException;public final synchronized void join(long millis) throws InterruptedException;public final synchronized void join(long millis, int nanos) throws InterruptedException;

其中

(1)三個方法都被final修飾,無法被子類重寫。

(2)join(long),join(long, long) 是synchronized method,同步的對象是當前線程實例。

(2)無參版本和兩個參數版本最終都調用了一個參數的版本。

(3) join() 和 join(0) 是等價的,表示一直等下去;join(非0)表示等待一段時間。

從源碼可以看到 join(0)調用了Object.wait(0),其中Object.wait(0)會一直等待,直到被notify/中斷才返回。

while(isAlive())是為了防止子線程偽喚醒(spurious wakeup),只要子線程沒有TERMINATED的,父線程就需要繼續等下去。

(4) join() 和 sleep() 一樣,可以被中斷(被中斷時,會拋出 InterrupptedException 異常);不同的是,join() 內部調用了 wait(),會出讓鎖,而 sleep() 會一直保持鎖。

以本文開頭的代碼為例,我們分析一下代碼邏輯:

調用鏈:Parent.main() -> child.join() -> child.join(0) -> child.wait(0)(此時 Parent線程會獲得 child 實例作為鎖,其他線程可以進入 child.join() ,但不可以進入 child.join(0), 因為child.join(0)是同步方法)。

如果 child 線程是 Active,則調用 child.wait(0)(為了防止子線程 spurious wakeup, 需要將 wait(0) 放入while(isAlive())循環中。

一旦 child 線程不為 Active (狀態為 TERMINATED),child.notifyAll()會被調用-> child.wait(0)返回 -> child.join(0)返回 -> child.join()返回 -> Parent.main()繼續執行, 子線程會調用this.notify(),child.wait(0)會返回到child.join(0) ,child.join(0)會返回到 child.join(), child.join() 會返回到 Parent 父線程,Parent 父線程就可以繼續運行下去了。

3. 對網上其他分析 join() 的文章提出疑問

我覺得網上很多文章的描述有歧義,下面挑選一些描述進行分析,也歡迎大家留言一起討論。

a. 子線程結束之后,'會喚醒主線程',父線程重新獲取cpu執行權,繼續運行。

這里感謝kerwinX的留言,子線程結束后,子線程的this.notifyAll()會被調用,join()返回,父線程只要獲取到鎖和CPU,就可以繼續運行下去了。

b. join() 將幾個并行的線程'合并為一個單線程'執行。

我理解這個說法的意思,但是這樣描述只會讓讀者更難理解。

在調用 join() 方法的程序中,原來的多個線程仍然多個線程,并沒有發生“合并為一個單線程”。真正發生的是調用join() 的線程進入 TIMED_WAITING 狀態,等待 join() 所屬線程運行結束后再繼續運行。

一點感想:技術人員寫作技術文章時,最好盡量避免使用過于口語化的詞匯。

因為這種詞匯歧義比較大,會讓讀者感到更加困惑或形成錯誤的理解。

到此這篇關于Java中Thread.join()的使用方法的文章就介紹到這了,更多相關Java Thread.join()內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 壹作文_中小学生优秀满分作文大全 | 山西3A认证|太原AAA信用认证|投标AAA信用证书-山西AAA企业信用评级网 | LED投光灯-工矿灯-led路灯头-工业灯具 - 山东普瑞斯照明科技有限公司 | 废气处理设备-工业除尘器-RTO-RCO-蓄热式焚烧炉厂家-江苏天达环保设备有限公司 | 中空玻璃生产线,玻璃加工设备,全自动封胶线,铝条折弯机,双组份打胶机,丁基胶/卧式/立式全自动涂布机,玻璃设备-山东昌盛数控设备有限公司 | 杭州货架订做_组合货架公司_货位式货架_贯通式_重型仓储_工厂货架_货架销售厂家_杭州永诚货架有限公司 | 真空干燥烘箱_鼓风干燥箱 _高低温恒温恒湿试验箱_光照二氧化碳恒温培养箱-上海航佩仪器 | CTP磁天平|小电容测量仪|阴阳极极化_双液系沸点测定仪|dsj电渗实验装置-南京桑力电子设备厂 | 齿轮减速电机一体机_蜗轮蜗杆减速马达-德国BOSERL齿轮减速机带电机生产厂家 | 废旧物资回收公司_广州废旧设备回收_报废设备物资回收-益美工厂设备回收公司 | 苏商学院官网 - 江苏地区唯一一家企业家自办的前瞻型、实操型商学院 | 急救箱-应急箱-急救包厂家-北京红立方医疗设备有限公司 | 塑钢课桌椅、学生课桌椅、课桌椅厂家-学仕教育设备首页 | 净化车间_洁净厂房_净化公司_净化厂房_无尘室工程_洁净工程装修|改造|施工-深圳净化公司 | 不干胶标签-不干胶贴纸-不干胶标签定制-不干胶标签印刷厂-弗雷曼纸业(苏州)有限公司 | 聚合氯化铝-碱式氯化铝-聚合硫酸铁-聚氯化铝铁生产厂家多少钱一吨-聚丙烯酰胺价格_河南浩博净水材料有限公司 | 丹尼克尔拧紧枪_自动送钉机_智能电批_柔性振动盘_螺丝供料器品牌 | 耐腐蚀泵,耐腐蚀真空泵,玻璃钢真空泵-淄博华舜耐腐蚀真空泵有限公司 | 烽火安全网_加密软件、神盾软件官网 | 丹佛斯压力传感器,WISE温度传感器,WISE压力开关,丹佛斯温度开关-上海力笙工业设备有限公司 | 全国国际化学校_国际高中招生_一站式升学择校服务-国际学校网 | 超声骨密度仪-动脉硬化检测仪器-人体成分分析仪厂家/品牌/价格_南京科力悦 | 雪花制冰机(实验室雪花制冰机)百科 | 艺术生文化课培训|艺术生文化课辅导冲刺-济南启迪学校 | 河南中专学校|职高|技校招生-河南中职中专网 | 干式变压器厂_干式变压器厂家_scb11/scb13/scb10/scb14/scb18干式变压器生产厂家-山东科锐变压器有限公司 | atcc网站,sigma试剂价格,肿瘤细胞现货,人结肠癌细胞株购买-南京科佰生物 | 深圳公司注册-工商注册代理-注册公司流程和费用_护航财税 | 动物麻醉机-数显脑立体定位仪-北京易则佳科技有限公司 | 工业胀紧套_万向节联轴器_链条-规格齐全-型号选购-非标订做-厂家批发价格-上海乙谛精密机械有限公司 | 家德利门业,家居安全门,别墅大门 - 安徽家德利门业有限公司 | 运动木地板厂家_体育木地板安装_篮球木地板选购_实木运动地板价格 | 温湿度记录纸_圆盘_横河记录纸|霍尼韦尔记录仪-广州汤米斯机电设备有限公司 | 希望影视-高清影视vip热播电影电视剧免费在线抢先看 | 杭州中央空调维修_冷却塔/新风机柜/热水器/锅炉除垢清洗_除垢剂_风机盘管_冷凝器清洗-杭州亿诺能源有限公司 | 农业四情_农业气象站_田间小型气象站_智慧农业气象站-山东风途物联网 | 北京宣传片拍摄_产品宣传片拍摄_宣传片制作公司-现像传媒 | 网络推广公司_网络营销方案策划_企业网络推广外包平台-上海澜推网络 | 氢氧化钙设备, 氢氧化钙生产线-淄博惠琛工贸有限公司 | 振动筛-交叉筛-螺旋筛-滚轴筛-正弦筛-方形摇摆筛「新乡振动筛厂家」 | 拉力测试机|材料拉伸试验机|电子拉力机价格|万能试验机厂家|苏州皖仪实验仪器有限公司 |