我编写了以下方法来并行运行多个线程,当所有线程都完成时,我想触发一些进一步的操作。我已将propertyChangeListener附加到在其自己的线程中运行的每个对象,并且每个对象在其线程完成时触发属性更改事件。因此,在每个事件中,我增加一个计数并将其与对象列表的大小进行比较。一旦它们相等,我知道所有线程都已完成。然而,这看起来有点像哈希,我对多线程很陌生,所以我想我会问别人对我的方法的看法,以及是否有更优雅或更强大的方法。感谢。
private void jButtonRunSubsetsActionPerformed(java.awt.event.ActionEvent evt) {
count = 0;
List<SpeciesSelection> specSelList = new ArrayList<>();
for (String str : fileList) {
// TODO RUN THE FILES
if (!str.equals("")) {
String[] args = {str};
//run solution
SpeciesSelection specSel = new SpeciesSelection(args, true);
specSelList.add(specSel);// add the thread to the list so we can check for all threads to be finished.
// Create listener to listen for specSel finished
specSel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// TODO do something
count++;
if (count == specSelList.size())
{
System.out.println("Finished all threads");
}
}
});
Thread t = new Thread(specSel);
t.start();
}
}
}
答案 0 :(得分:2)
而不是使用int
计数器并检查其值,使用专为此设计的CountDownLatch
。
CountDownLatch count = new CountDownLatch(nbRequiredCount);
count.await();
await()
在计数器不到0
时不会返回。
并在线程中减少它:
public void propertyChange(PropertyChangeEvent evt) {
// TODO do something
count.countDown();
}
答案 1 :(得分:0)
您可以像这样使用课程CountDownLatch
:
CountDownLatch latch = new CountDownLatch(N);
其中N
是您启动的线程数。您传递此对象并在每次线程完成时调用latch.countDown()
。一旦完成,锁存器将释放对父线程的控制。
答案 2 :(得分:0)
使用给出的建议,我改变了我的代码如下:
private void jButtonRunSubsetsActionPerformed(java.awt.event.ActionEvent evt) {
List<SpeciesSelection> specSelList = new ArrayList<>();
new Thread() {
@Override
public void run() {
try {
int numberFiles = fileList.size();
CountDownLatch latch = new CountDownLatch(numberFiles);
for (String str : fileList) {
// TODO RUN THE FILES
if (!str.equals("")) {
String[] args = {str};
//run solution
SpeciesSelection specSel = new SpeciesSelection(args, true);
specSelList.add(specSel);// add the thread to the list so we can check for all threads to be finished.
// Create listener to listen for specSel finished
specSel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
latch.countDown();
}
});
Thread t = new Thread(specSel);
t.start();
}
}
latch.await();
System.out.println("Finished all threads");
} catch (InterruptedException ex) {
Logger.getLogger(SpecSelGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
我按照建议使用了CountDownLatch,但是在一个额外的匿名线程中运行了多个进程,这样我就可以调用latch.await()而不会冻结主线程/ GUI响应。