检测多线程何时完成的正确方法-Java
我编写了以下方法来并行运行多个线程,当所有线程都完成时,我想触发一些进一步的操作。我已将propertyChangeListener附加到在其自己的线程中运行的每个对象,这些对象中的每个对象在其线程完成时都会触发一个property changed事件。因此,在每一个事件上,我增加一个计数,并将其与对象列表的大小进行比较。一旦它们相等,我就知道所有的线程都完成了。然而,这似乎有点混乱,而且我对多线程非常陌生,所以我想问问其他人对我的方法的看法,以及是否有更优雅或更健壮的方法。谢谢检测多线程何时完成的正确方法-Java,java,multithreading,Java,Multithreading,我编写了以下方法来并行运行多个线程,当所有线程都完成时,我想触发一些进一步的操作。我已将propertyChangeListener附加到在其自己的线程中运行的每个对象,这些对象中的每个对象在其线程完成时都会触发一个property changed事件。因此,在每一个事件上,我增加一个计数,并将其与对象列表的大小进行比较。一旦它们相等,我就知道所有的线程都完成了。然而,这似乎有点混乱,而且我对多线程非常陌生,所以我想问问其他人对我的方法的看法,以及是否有更优雅或更健壮的方法。谢谢 private
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();
}
}
}
private void jButtonRunSubsetsActionPerformed(java.awt.event.ActionEvent evt){
计数=0;
List specSelList=new ArrayList();
for(字符串str:fileList){
//要运行这些文件吗
如果(!str.equals(“”){
字符串[]args={str};
//运行解决方案
SpeciesSelection specSel=新SpeciesSelection(args,true);
specseList.add(specSel);//将线程添加到列表中,这样我们就可以检查所有要完成的线程。
//创建侦听器以侦听specSel已完成
specSel.addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
//做点什么
计数++;
if(count==specSelList.size())
{
System.out.println(“完成所有线程”);
}
}
});
螺纹t=新螺纹(specSel);
t、 start();
}
}
}
您可以像这样使用类倒计时闩锁
:
CountDownLatch latch = new CountDownLatch(N);
其中
N
是您启动的线程数。每次线程结束时,您都会传递这个对象并调用latch.countDown()
。完成所有操作后,闩锁将释放对父线程的控制。您可以像这样使用类CountDownLatch
:
CountDownLatch latch = new CountDownLatch(N);
其中
N
是您启动的线程数。每次线程结束时,您都会传递这个对象并调用latch.countDown()
。完成所有操作后,闩锁将释放对父线程的控制。而不是使用int
计数器,并检查其值使用设计为的CountDownLatch
CountDownLatch count = new CountDownLatch(nbRequiredCount);
count.await();
计数器未设置为0
时,wait()
不会返回
并在线程中递减:
public void propertyChange(PropertyChangeEvent evt) {
// TODO do something
count.countDown();
}
不要使用
int
计数器并检查其值,而应使用设计为的CountDownLatch
CountDownLatch count = new CountDownLatch(nbRequiredCount);
count.await();
计数器未设置为0
时,wait()
不会返回
并在线程中递减:
public void propertyChange(PropertyChangeEvent evt) {
// TODO do something
count.countDown();
}
根据给出的建议,我将代码修改如下:
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();
}
private void jButtonRunSubsetsActionPerformed(java.awt.event.ActionEvent evt){
List specSelList=new ArrayList();
新线程(){
@凌驾
公开募捐{
试一试{
int numberFiles=fileList.size();
CountDownLatch闩锁=新的CountDownLatch(numberFiles);
for(字符串str:fileList){
//要运行这些文件吗
如果(!str.equals(“”){
字符串[]args={str};
//运行解决方案
SpeciesSelection specSel=新SpeciesSelection(args,true);
specseList.add(specSel);//将线程添加到列表中,这样我们就可以检查所有要完成的线程。
//创建侦听器以侦听specSel已完成
specSel.addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
倒计时();
}
});
螺纹t=新螺纹(specSel);
t、 start();
}
}
satch.wait();
System.out.println(“完成所有线程”);
}捕获(中断异常例外){
Logger.getLogger(SpecSelGUI.class.getName()).log(Level.SEVERE,null,ex);
}
}
}.start();
}
我按照建议使用了CountDownLatch,但也在一个额外的匿名线程中运行了多个进程,这样我就可以在不冻结主线程/GUI响应的情况下调用latch.await()。使用给出的建议,我修改了代码,如下所示:
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();
}
private void jButtonRunSubsetsActionPerformed(java.awt.event.ActionEvent evt){
List specSelList=new ArrayList();
新线程(){
@凌驾
公开募捐{
试一试{
int numberFiles=fileList.size();
CountDownLatch闩锁=新的CountDownLatch(numberFiles);
for(字符串str:fileList){
//要运行这些文件吗
如果(!str.equals(“”){
字符串[]args={str};
//运行解决方案
SpeciesSelection specSel=新SpeciesSelection(args,true);
specSelList.add(specSel);//将线程添加到列表中以便我们可以检查