Java判斷線程池線程是否執(zhí)行完畢
在使用多線程的時候有時候我們會使用 java.util.concurrent.Executors的線程池,當多個線程異步執(zhí)行的時候,我們往往不好判斷是否線程池中所有的子線程都已經(jīng)執(zhí)行完畢,但有時候這種判斷卻很有用,例如我有個方法的功能是往一個文件異步地寫入內(nèi)容,我需要在所有的子線程寫入完畢后在文件末尾寫“---END---”及關(guān)閉文件流等,這個時候我就需要某個標志位可以告訴我是否線程池中所有的子線程都已經(jīng)執(zhí)行完畢,我使用這種方式來判斷。
public class MySemaphore {
public static void main(String[] args) throws IOException, InterruptedException {
final File stream = new File("c:\\temp\\stonefeng\\stream.txt");
final OutputStream os = new FileOutputStream(stream);
final OutputStreamWriter writer = new OutputStreamWriter(os);
final Semaphore semaphore = new Semaphore(10);
ExecutorService exec = Executors.newCachedThreadPool();
final long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
final int num = i;
Runnable task = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
writer.write(String.valueOf(num)+"\n");
semaphore.release();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.submit(task);
}
exec.shutdown();
while(true){
if(exec.isTerminated()){
writer.write("---END---\n");
writer.close();
System.out.println("所有的子線程都結(jié)束了!");
break;
}
Thread.sleep(1000);
}
final long end = System.currentTimeMillis();
System.out.println((end-start)/1000);
}
}
當調(diào)用ExecutorService.shutdown方法的時候,線程池不再接收任何新任務(wù),但此時線程池并不會立刻退出,直到添加到線程池中的任務(wù)都已經(jīng)處理完成,才會退出。在調(diào)用shutdown方法后我們可以在一個死循環(huán)里面用isTerminated方法判斷是否線程池中的所有線程已經(jīng)執(zhí)行完畢,如果子線程都結(jié)束了,我們就可以做關(guān)閉流等后續(xù)操作了。
判斷線程池中的線程是否全部執(zhí)行完畢的另外一種解決方案則是使用閉鎖(CountDownLatch)來實現(xiàn),CountDownLatch是一種靈活的閉鎖實現(xiàn),它可以使一個或多個線程等待一組事件發(fā)生。閉鎖狀態(tài)包括一個計數(shù)器,該計數(shù)器被初始化為一個正數(shù),表示需要等待的事件數(shù)量。countDown方法遞減計數(shù)器,表示有一個事件已經(jīng)發(fā)生了,而await方法等待計數(shù)器達到零,即表示需要等待的事情都已經(jīng)發(fā)生。可以使用閉鎖來這樣設(shè)計程序達到目的:
public class CountDownLatchApproach {
public static void main(String[] args) throws IOException, InterruptedException {
final int nThreads = 10;
final CountDownLatch endGate = new CountDownLatch(nThreads);
final File stream = new File("c:\\temp\\stonefeng\\stream.txt");
final OutputStream os = new FileOutputStream(stream);
final OutputStreamWriter writer = new OutputStreamWriter(os);
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < nThreads; i++) {
final int num = i;
Runnable task = new Runnable() {
@Override
public void run() {
try {
writer.write(String.valueOf(num)+"\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
endGate.countDown();
}
}
};
exec.submit(task);
}
endGate.await();
writer.write("---END---\n");
writer.close();
}
}
這種解決方案雖然可以達到目的但是性能差到?jīng)]朋友,我更傾向于使用第一種方案。
現(xiàn)在我們有了更優(yōu)雅的第三種方案,它的執(zhí)行性能也不錯。
public class MySemaphore {
public static void main(String[] args) throws IOException, InterruptedException {
final File stream = new File("c:\\temp\\stonefeng\\stream.txt");
final OutputStream os = new FileOutputStream(stream);
final OutputStreamWriter writer = new OutputStreamWriter(os);
final Semaphore semaphore = new Semaphore(10);
ExecutorService exec = Executors.newCachedThreadPool();
final long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
final int num = i;
Runnable task = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
writer.write(String.valueOf(num)+"\n");
semaphore.release();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.submit(task);
}
exec.shutdown();
exec.awaitTermination(1, TimeUnit.HOURS);
writer.write("---END---\n");
writer.close();
System.out.println("ËùÓеÄ×ÓÏ̶߳¼½áÊøÁË£¡");
final long end = System.currentTimeMillis();
System.out.println((end-start)/1000);
}
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java的web開發(fā)中SSH框架的協(xié)作處理應(yīng)用筆記
這篇文章主要介紹了Java的web開發(fā)中SSH框架的協(xié)作處理應(yīng)用筆記,SSH是指Struts和Spring以及Hibernate的框架搭配,需要的朋友可以參考下2015-12-12
Maven編譯遇到Process terminated問題(四種情況全部解決)
這篇文章主要介紹了Maven編譯遇到Process terminated問題(四種情況全部解決),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
Spring注解驅(qū)動之ApplicationListener用法解讀
這篇文章主要介紹了Spring注解驅(qū)動之ApplicationListener用法解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
Java8 Supplier接口和Consumer接口原理解析
這篇文章主要介紹了Java8 Supplier接口和Consumer接口原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04
java-RGB調(diào)色面板的實現(xiàn)(事件監(jiān)聽器之匿名內(nèi)部類)
這篇文章主要介紹了java-RGB調(diào)色面板的實現(xiàn)(事件監(jiān)聽器之匿名內(nèi)部類),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11
淺析Java中關(guān)鍵詞volatile底層的實現(xiàn)原理
在 Java 并發(fā)編程中,有 3 個最常用的關(guān)鍵字:synchronized、ReentrantLock 和 volatile,這篇文章主要來和大家聊聊volatile底層的實現(xiàn)原理,感興趣的可以了解下2024-02-02

