[英]Correct way to detect when multiple threads finished - Java
I wrote the following method to run multiple threads in parallel and when all threads are complete I want to trigger some further action. 我编写了以下方法来并行运行多个线程,当所有线程完成时,我想触发一些进一步的操作。 I've attached a propertyChangeListener to each object that runs in its own thread and each of those objects fires a property changed event when its thread completes. 我已将propertyChangeListener附加到在其自己的线程中运行的每个对象,并且每个对象在其线程完成时都会触发属性更改事件。 So on each of those events I increment a count and compare it to the size of the list of objects. 因此,在每个这些事件上,我都会增加一个计数,并将其与对象列表的大小进行比较。 Once they are equal I know all threads are finished. 一旦它们相等,我就知道所有线程都已完成。 However, this seems like a bit of a hash up and I'm quite new to multi-threading, so I thought I'd ask what others think of my approach and whether there are more elegant or robust approaches. 但是,这似乎有点杂乱无章,并且我对多线程还很陌生,所以我想问一下其他人对我的方法有何看法,以及是否有更优雅或更强大的方法。 Thanks. 谢谢。
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();
}
}
}
Rather than using an int
counter and check its value use CountDownLatch
that is designed to. 与其使用int
计数器并检查其值,不如使用设计为CountDownLatch
方法。
CountDownLatch count = new CountDownLatch(nbRequiredCount);
count.await();
The await()
doesn't return while the counter is not to 0
. 当计数器不为0
时, await()
不返回。
and decrement it in threads : 并在线程中递减:
public void propertyChange(PropertyChangeEvent evt) {
// TODO do something
count.countDown();
}
You can use the class CountDownLatch
like this: 您可以像这样使用CountDownLatch
类:
CountDownLatch latch = new CountDownLatch(N);
where N
is the number of threads you launch. 其中N
是您启动的线程数。 You pass around this object and call the latch.countDown()
each time a thread finishes. 传递该对象并在每次线程结束时调用latch.countDown()
。 Once they are all done, the latch will release control to the parent thread. 完成所有操作后,闩锁将控制权释放给父线程。
Using the advice given, I altered my code as follows: 使用给出的建议,我对代码进行了如下更改:
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();
}
I used the CountDownLatch as suggested but also ran the multiple processes inside an additional anonymous thread so that I could call latch.await() without freezing up the main thread/GUI responsiveness. 我按照建议使用了CountDownLatch,但还在一个额外的匿名线程中运行了多个进程,以便可以调用latch.await()而不冻结主线程/ GUI的响应速度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.