2014-12-02 33 views
0

我在java中有一組線程,我想多次運行(每次都有一組不同的參數)。第二輪比賽開始,我想等待第一輪比賽結束。這應該與Thread.join()輕鬆地完成第二輪之前,但因爲我的線程在一個無限循環中運行我有一箇中斷,這也中斷阻塞阻止他們加盟:如何等待一組線程'真的'在java中完成?

我有一個線程,其run()方法看起來基本上像這樣:

try { 
    while(true) { 
     printSomeInfo(); 
     if (...) { 
      Thread.currentThread().getThreadGroup().interrupt(); 
     } 
    } 
} catch (InterruptedException e) { 
    Thread.currentThread().getThreadGroup().interrupt(); 
} finally { 
    printStats(); 
} 

,並調用線程的run方法主要方法:

System.out.println("New run:"); 
for (i ...) { //first run 
    myThread[i] = new MyThread(someInfoString1); 
    myThread[i].start(); 
} 
try { 
    for (i...) { 
     myThread[i].join(); 
    } 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 
System.out.println("New run:"); 
for (i ...) { //second run 
    myThread[i] = new MyThread(someInfoString2); 
    myThread[i].start(); 
} 
try { 
    for (i...) { 
     myThread[i].join(); 
    } 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 

我的問題是第二輪開始打印出來的信息,而第一個R un正在使用finally塊中的printStats()方法完成打印。 所以輸出看起來是這樣的:

New run: 
Info 1 
Info 1 
... 
Info 1 
New run: 
(here comes the stack trace) 
Info 2 
Info 2 
Stats 1 <- this should happen before the second "New run:" 
... 
Info 2 
Stats 2 

如何我真的能等到第一線組的完嗎?是否有更多選擇性的方式來中斷正在運行的線程?

+3

[CyclicBarrier](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html) – 2014-12-02 09:20:00

+3

如果一段代碼必須在另一位之後運行,爲什麼不使用一個線程? – Bathsheba 2014-12-02 09:23:03

+0

因爲某些部分應該平行進行? OP使用* one *線程編排其他線程。 – aioobe 2014-12-02 09:27:26

回答

2

問題就出在你反覆使用的Thread.currentThread().getThreadGroup().interrupt()這中斷在ThreadGroup所有線程,其中包括被稱爲join之一。

如果你看看你的循環,你正在趕上InterruptedException,但沒有正確恢復。您的循環包含在try…catch塊中,因此由異常強制終止。既然你要撥打join上的所有線程,則必須使用循環進行,包括已中斷了一個join電話:

threads: for (i...) { // loop over all threads 
    for(;;) { // recover join on InterruptedException 
     try { 
      myThread[i].join(); 
      continue threads; // after successful join 
     } catch (InterruptedException e) {} // call join again 
    } 
} 

一般來說,中斷整個ThreadGroup,或處理線程組的過時的概念根本不是一個合適的軟件設計。您應該重新編寫軟件以僅中斷有意線程。或者直接使用併發框架,尤其是。 ExecutorService已經提供了提交任務組並取消或等待所有任務的方法。