【问题标题】:java wait all threads in pooljava等待池中的所有线程
【发布时间】:2011-12-01 15:50:45
【问题描述】:

有没有办法在按下暂停按钮并按下重新运行播放按钮时等待执行程序池中的所有线程?我试过 CountDownLatch 但我不知道我必须把它放在 executor 声明之后还是 run() 方法中?我没有太多关于线程的信息。请有人告诉我该怎么做。谢谢

 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();
    }


}

【问题讨论】:

    标签: java multithreading swing


    【解决方案1】:

    您的机器人工作人员需要一种共享线程安全的方式来检查工作人员是否应该暂停或播放。在你的 worker 的 run() 方法中,如果线程被暂停,等待这个锁对象的通知。在循环时,或者无论工作人员做什么,定期检查锁的状态,并在需要时暂停工作人员。

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

    您的暂停和播放按钮应该在 workerLock 上获得同步锁,并设置 paused 属性,并在 workerLock 上调用 notify()。这将使工作人员根据需要暂停或继续。无论暂停/播放状态如何,Executor 始终“运行”。

    编辑 可以将上面的代码重构为自己的类,如下:

    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);
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 我现在可以暂停,但不能继续。你能看看有什么问题吗? while(true){ if(Frame.pause==true){ try { Thread.currentThread().wait(); } else{ if(end==false){// 没有到达出口...运行我的方法
    • 您正在线程上调用 wait()。相反,您应该在某个任意对象上调用 wait()。 wait() 实际上是 Object 中的一个方法,而不是 Thread。正在等待的对象应该由所有工作人员共享,并且当状态发生变化时,swing 按钮应该在该对象上调用 notify()。
    • 是的,它不再起作用了:) 只是我改变了 notifyAll()。当使用 notify() 时,它只是恢复当前线程。非常感谢:)
    【解决方案2】:

    您可以等待所有线程完成:

    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

    【讨论】:

    • 谢谢你。但是我如何检查是否使用此方法按下了按钮。我知道它可以根据确定的等待时间工作。
    • @user1073777:您必须将此代码放在暂停按钮的 actionListener 中。此代码将等待所有线程完成。
    • 好的,它正在工作,但 60 秒并开始自行继续。我想等到按下播放按钮。我的意思是我不知道何时按下播放按钮,也不能写时间而不是 '60 ':(
    • 不,此方法等待线程完成工作或 60 秒过去,以先到者为准。
    猜你喜欢
    • 2017-04-29
    • 1970-01-01
    • 2018-07-24
    • 2015-04-17
    • 1970-01-01
    • 2019-10-08
    • 2020-03-27
    • 2019-10-24
    • 2015-08-29
    相关资源
    最近更新 更多