java等待池中的所有线程

时间:2011-12-01 15:50:45

标签: java multithreading swing

当按下暂停按钮并重新按下播放按钮时,有没有办法等待执行程序池中的所有线程?我尝试过CountDownLatch,但我不知道我必须在执行器声明或run()方法之后放置它吗?我没有太多关于threads.sase的信息,有人可以告诉我我该怎么做。谢谢

 public static CountDownLatch waiter;
public static ExecutorService pool;

public Action() throws InterruptedException{
    pool=Executors.newFixedThreadPool(2);
    waiter=new CountDownLatch(2); // to wait
    robot1=new Robot(0,560,"rbt1"); // starts random free position
    robot2=new Robot(0,560,"rbt2");
    if(Frame.pause==false){
       pool.submit(robot1);
       pool.submit(robot2);}
    if(Frame.pause==true){
        waiter.await();
    }


}

2 个答案:

答案 0 :(得分:0)

您可以等待所有主题完成:

pool.awaitTermination(60, TimeUnit.SECONDS); // hopefully 60 seconds are enough

请参阅:http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination%28long,%20java.util.concurrent.TimeUnit%29

答案 1 :(得分:0)

您的机器人工作人员需要一种共享的线程安全方式来检查工作人员是应该暂停还是正在玩。在工作程序的run()方法中,如果线程暂停,请等待此锁定对象的通知。在循环时,或者工作者做的任何事情,定期检查锁的状态,并在需要时暂停工作。

pauseIfNeeded() {
    synchronized(workerLock) {
        if (workerLock.isPaused()) {
            workerLock.wait();
        }
    }
}

您的暂停和播放按钮应该在workerLock上获得同步锁定,并设置暂停属性,并在workerLock上调用notify()。这将让工人根据需要暂停或继续。无论暂停/播放状态如何,执行者总是“正在运行”。

修改 您可以将上面的代码重构为它自己的类,如下所示:

public class WorkerPauseManager {

    private boolean paused;

    public synchronized void pauseIfNeeded() throws InterruptedException {
        if (paused) wait();
    }

    public synchronized void pause() {
        this.paused = true;
    }

    public synchronized void start() {
        this.paused = false;
        notifyAll();
    }
}

创建一个WorkerPauseManager实例。将此实例传递给所有机器人工作人员,并保留参考摆动暂停/播放动作的参考。您的工作线程应该调用pauseIfNeeded。

这是使用WorkerPauseManager的SCCE:

public class WorkerPauseManagerTest {
    public static void main(String[] args) {
        final WorkerPauseManager pauseManager = new WorkerPauseManager();
        new Worker("Worker 1", pauseManager).start();
        new Worker("Worker 2", pauseManager).start();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JToggleButton playPauseButton = new JToggleButton(new AbstractAction("Pause") {
                    public void actionPerformed(final ActionEvent e) {
                        JToggleButton source = (JToggleButton) e.getSource();
                        if (source.isSelected()) {
                            pauseManager.start();
                            source.setText("Pause");
                        } else {
                            pauseManager.pause();
                            source.setText("Play");
                        }
                    }
                });
                JOptionPane.showMessageDialog(null, playPauseButton, "WorkerPauseManager Demo", JOptionPane.PLAIN_MESSAGE);
                System.exit(0);
            }
        });

    }

    private static class Worker extends Thread {
        final String name;
        final WorkerPauseManager pauseManager;

        public Worker(final String name, final WorkerPauseManager pauseManager) {
            this.name = name;
            this.pauseManager = pauseManager;
        }

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                try {
                    pauseManager.pauseIfNeeded();
                    System.out.println(name + " is running");
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}