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

问题描述 投票:0回答:3

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

而不是使用int计数器并检查其值使用设计的CountDownLatch

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

await()不会返回,而柜台不是0

并在线程中减少它:

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

0
投票

您可以像这样使用CountDownLatch类:

CountDownLatch latch = new CountDownLatch(N);

其中N是您启动的线程数。你传递这个对象并在每次线程完成时调用latch.countDown()。完成所有操作后,锁存器将释放对父线程的控制权。


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响应。

© www.soinside.com 2019 - 2024. All rights reserved.