Java并發(fā)編程示例(六):等待線程執(zhí)行終止
在某些場(chǎng)景下,我們必須等待線程執(zhí)行完成才能進(jìn)行下一步工作。例如,某些程序在開始執(zhí)行之前,需要先初始化一些資源。這時(shí),我們可以啟動(dòng)一個(gè)線程專門來做初始化任務(wù),等到線程任務(wù)完成后,再去執(zhí)行其他部分。
為此,Thread類為我們提供了join()方法。當(dāng)我們使用線程對(duì)象調(diào)用此方法時(shí),正在掉調(diào)用的線程對(duì)象將被推遲到被調(diào)用對(duì)象執(zhí)行完成后再開始執(zhí)行。
在本節(jié),示例程序演示等待初始化方法完成后,再去執(zhí)行其他任務(wù)。
知其然
按照下面所示步驟,完成示例程序。
1.創(chuàng)建一個(gè)名為DataSourcesLoader的類,并且實(shí)現(xiàn)Runnable接口。代碼如下:
public class DataSourcesLoader implements Runnable {
2.實(shí)現(xiàn)run()方法,向控制臺(tái)打印出一條信息以說明開始執(zhí)行,然后睡眠4秒鐘,再向控制臺(tái)打印一條信息來說明線程執(zhí)行結(jié)束。代碼如下:
@Override
public void run() {
System.out.printf("Beginning data sources loading: %s\n",
new Date());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Data sources loading has finished: %s\n",
new Date());
}
3.創(chuàng)建一個(gè)名為NetworkConnectionsLoader的類,并且實(shí)現(xiàn)Runnable接口。 實(shí)現(xiàn)run()方法,該方法代碼與DataSourcesLoader類的run()方法一樣,只是這個(gè)睡眠6秒鐘。
4.實(shí)現(xiàn)示例的主類,并且實(shí)現(xiàn)main()方法。代碼如下:
public class Main {
public static void main(String[] args) {
5.創(chuàng)建一個(gè)DataSourcesLoader對(duì)象,以及一個(gè)啟動(dòng)它執(zhí)行的Thread對(duì)象。代碼如下:
DataSourcesLoader dsLoader = new DataSourcesLoader();
Thread thread1 = new Thread(dsLoader, "DataSourcesLoader");
6.創(chuàng)建一個(gè)NetworkConnectionsLoader對(duì)象,以及一個(gè)啟動(dòng)它執(zhí)行的Thread對(duì)象。代碼如下:
NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
Thread thread2 = new Thread(ncLoader, "NetworkConnectionsLoader");
7.調(diào)用兩個(gè)Thread對(duì)象的start()方法。代碼如下:
thread1.start();
thread2.start();
8.調(diào)用join()方法,來等待兩個(gè)線程完成其任務(wù)。這個(gè)方法會(huì)拋出InterruptedException異常,所以要捕獲該異常。代碼如下:
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
9.向控制臺(tái)打印一句話,表明程序執(zhí)行結(jié)束。代碼如下:
System.out.printf("Main: Configuration has been loaded: %s\n",
new Date());
10.運(yùn)行程序,查看執(zhí)行效果。
知其所以然
當(dāng)運(yùn)行這個(gè)示例程序時(shí),我們可以看到兩個(gè)線程啟動(dòng)了它們的執(zhí)行。首先,是DataSourcesLoader完成了它的執(zhí)行;然后,是NetworkConnectionsLoader完成了它的執(zhí)行。這時(shí),主線程繼續(xù)它的執(zhí)行,然后向控制臺(tái)打印出終止信息。
永無止境
Java提供了另外兩種重載的join()方法:
join(long milliseconds)
join(long milliseconds, long nanos)
第一種方式,不會(huì)直到被調(diào)用完成任務(wù),而是等待參數(shù)指定的時(shí)間后就開始執(zhí)行;例如,如果thread1調(diào)用該方法,thread1.join(1000),當(dāng)thread1線程滿足如下其中之一的條件就會(huì)繼續(xù)執(zhí)行:
1.thread2完成它的執(zhí)行;
2.1000毫秒過后;
當(dāng)這兩個(gè)條件中的其中之一為真時(shí),join()方法就會(huì)返回,開始繼續(xù)執(zhí)行原來的任務(wù)。
第二種方式的方法和第一種很類似,只是多了一個(gè)納秒級(jí)的時(shí)間參數(shù)。
拿來主義
本文是從 《Java 7 Concurrency Cookbook》 (D瓜哥竊譯為 《Java7并發(fā)示例集》 )翻譯而來,僅作為學(xué)習(xí)資料使用。沒有授權(quán),不得用于任何商業(yè)行為。
小有所成
本節(jié)所用示例代碼的完整版。
DataSourcesLoader類的完整代碼
package com.diguage.books.concurrencycookbook.chapter1.recipe6;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* Date: 2013-09-19
* Time: 09:15
*/
public class DataSourcesLoader implements Runnable {
@Override
public void run() {
System.out.printf("Beginning data sources loading: %s\n",
new Date());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Data sources loading has finished: %s\n",
new Date());
}
}
NetworkConnectionsLoader類的完整代碼
package com.diguage.books.concurrencycookbook.chapter1.recipe6;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* Date: 2013-09-19
* Time: 09:21
*/
public class NetworkConnectionsLoader implements Runnable {
@Override
public void run() {
System.out.printf("Beginning data sources loading: %s\n",
new Date());
try {
TimeUnit.SECONDS.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Data sources loading has finished: %s\n",
new Date());
}
}
Main類的完整代碼
package com.diguage.books.concurrencycookbook.chapter1.recipe6;
import java.util.Date;
/**
* Date: 2013-09-19
* Time: 09:25
*/
public class Main {
public static void main(String[] args) {
DataSourcesLoader dsLoader = new DataSourcesLoader();
Thread thread1 = new Thread(dsLoader, "DataSourcesLoader");
NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
Thread thread2 = new Thread(ncLoader, "NetworkConnectionsLoader");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Main: Configuration has been loaded: %s\n",
new Date());
}
}
相關(guān)文章
Java堆空間爆滿導(dǎo)致宕機(jī)的問題分析及解決
團(tuán)隊(duì)有一個(gè)服務(wù),一直運(yùn)行的好好的,突然訪問異常了,先是請(qǐng)求超時(shí),然后直接無法訪問,本文將給大家介紹Java堆空間爆滿導(dǎo)致宕機(jī)的問題分析及解決,需要的朋友可以參考下2024-02-02
詳解Java?POI?excel自定義設(shè)置單元格格式
這篇文章主要介紹了Java?POI?excel設(shè)置單元格格式,自定義設(shè)置,設(shè)置單元格格式:來源_formats,更多數(shù)據(jù)類型從formats里面發(fā)現(xiàn),需要的朋友可以參考下2024-01-01
java 獲取服務(wù)器真實(shí)IP的實(shí)例
這篇文章主要介紹了java 獲取服務(wù)器真實(shí)IP的實(shí)例的相關(guān)資料,這里提供實(shí)現(xiàn)方法幫助大家學(xué)習(xí)理解這部分內(nèi)容,需要的朋友可以參考下2017-08-08
詳解java之redis篇(spring-data-redis整合)
本篇文章主要介紹了java之redis篇,主要詳細(xì)的介紹了spring-data-redis整合,有興趣的可以了解一下。2017-01-01
Java數(shù)據(jù)結(jié)構(gòu)--時(shí)間和空間復(fù)雜度
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)的時(shí)間和空間復(fù)雜度,小編覺得這篇文寫的不錯(cuò),感興趣的朋友可以了解下,希望能夠給你帶來幫助2021-08-08
Java泛型機(jī)制與反射原理相關(guān)知識(shí)總結(jié)
今天帶大家學(xué)習(xí)的是關(guān)于Java進(jìn)階的相關(guān)知識(shí),文章圍繞著Java泛型機(jī)制與反射原理展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
利用Java實(shí)現(xiàn)簡(jiǎn)單的猜數(shù)字小游戲
這篇文章主要為大家詳細(xì)介紹了如何利用java語言實(shí)現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
linux中nohup?java?-jar啟動(dòng)java項(xiàng)目的步驟
nohup是一個(gè)Unix和Linux命令,用于運(yùn)行關(guān)閉時(shí)不會(huì)被終止的進(jìn)程,這篇文章主要給大家介紹了關(guān)于linux中nohup?java?-jar啟動(dòng)java項(xiàng)目的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08
java數(shù)據(jù)結(jié)構(gòu)之二分查找法 binarySearch的實(shí)例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)之二分查找法 binarySearch的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10
springboot?ElasticSearch如何配置自定義轉(zhuǎn)換器ElasticsearchCustomConver
這篇文章主要介紹了springboot?ElasticSearch如何配置自定義轉(zhuǎn)換器ElasticsearchCustomConversions問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08

