Waiting for multiple SwingWorkers

前端 未结 2 1013
野的像风
野的像风 2020-11-22 03:32

Please consider the following code fragment:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java         


        
2条回答
  •  南方客
    南方客 (楼主)
    2020-11-22 03:41

    I intend to remove all of the labels together when all of the workers have completed their tasks.

    As described here, a CountDownLatch works well in this context. In the example below, each worker invokes latch.countDown() on completion, and a Supervisor worker blocks on latch.await() until all tasks complete. For demonstration purposes, the Supervisor updates the labels. Wholesale removal, shown in comments, is technically possible but generally unappealing. Instead, consider a JList or JTable.

    Worker Latch Test

    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    import java.util.Random;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import javax.swing.*;
    
    /**
    * @see https://stackoverflow.com/a/11372932/230513
    * @see https://stackoverflow.com/a/3588523/230513
    */
    public class WorkerLatchTest extends JApplet {
    
        private static final int N = 8;
        private static final Random rand = new Random();
        private Queue labels = new LinkedList();
        private JPanel panel = new JPanel(new GridLayout(0, 1));
        private JButton startButton = new JButton(new StartAction("Do work"));
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    JFrame frame = new JFrame();
                    frame.setTitle("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new WorkerLatchTest().createGUI());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        @Override
        public void init() {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    add(new WorkerLatchTest().createGUI());
                }
            });
        }
    
        private JPanel createGUI() {
            for (int i = 0; i < N; i++) {
                JLabel label = new JLabel("0", JLabel.CENTER);
                label.setOpaque(true);
                panel.add(label);
                labels.add(label);
            }
            panel.add(startButton);
            return panel;
        }
    
        private class StartAction extends AbstractAction {
    
            private StartAction(String name) {
                super(name);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                    startButton.setEnabled(false);
                    CountDownLatch latch = new CountDownLatch(N);
                    ExecutorService executor = Executors.newFixedThreadPool(N);
                    for (JLabel label : labels) {
                        label.setBackground(Color.white);
                        executor.execute(new Counter(label, latch));
                    }
                    new Supervisor(latch).execute();
            }
        }
    
        private class Supervisor extends SwingWorker {
    
            CountDownLatch latch;
    
            public Supervisor(CountDownLatch latch) {
                this.latch = latch;
            }
    
            @Override
            protected Void doInBackground() throws Exception {
                latch.await();
                return null;
            }
    
            @Override
            protected void done() {
                for (JLabel label : labels) {
                    label.setText("Fin!");
                    label.setBackground(Color.lightGray);
                }
                startButton.setEnabled(true);
                //panel.removeAll(); panel.revalidate(); panel.repaint();
            }
        }
    
        private static class Counter extends SwingWorker {
    
            private JLabel label;
            CountDownLatch latch;
    
            public Counter(JLabel label, CountDownLatch latch) {
                this.label = label;
                this.latch = latch;
            }
    
            @Override
            protected Void doInBackground() throws Exception {
                int latency = rand.nextInt(42) + 10;
                for (int i = 1; i <= 100; i++) {
                    publish(i);
                    Thread.sleep(latency);
                }
                return null;
            }
    
            @Override
            protected void process(List values) {
                label.setText(values.get(values.size() - 1).toString());
            }
    
            @Override
            protected void done() {
                label.setBackground(Color.green);
                latch.countDown();
            }
        }
    }
    

提交回复
热议问题