繁体   English   中英

检测多个线程何时完成的正确方法-Java

[英]Correct way to detect when multiple threads finished - Java

我编写了以下方法来并行运行多个线程,当所有线程完成时,我想触发一些进一步的操作。 我已将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();
            }
        }
    }

与其使用int计数器并检查其值,不如使用设计为CountDownLatch方法。

CountDownLatch count = new CountDownLatch(nbRequiredCount);
count.await(); 

当计数器不为0时, await()不返回。

并在线程中递减:

public void propertyChange(PropertyChangeEvent evt) {
    // TODO do something
    count.countDown();
}

您可以像这样使用CountDownLatch类:

CountDownLatch latch = new CountDownLatch(N);

其中N是您启动的线程数。 传递该对象并在每次线程结束时调用latch.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();
    }

我按照建议使用了CountDownLatch,但还在一个额外的匿名线程中运行了多个进程,以便可以调用latch.await()而不冻结主线程/ GUI的响应速度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM