2014-12-02 34 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已经提供了提交任务组并取消或等待所有任务的方法。