java - 使用 SwingWorker java 在线程池中等待任务

标签 java multithreading swing user-interface swingworker

我在一个线程内模拟多个任务 - 当所有任务都应该向 GUI 报告时。所以我有一个独特的表单,里面有 4 个面板,它们应该回复并执行不同的任务.. 他们每个人都应该继续汇集一个数据库并向 GUI 报告内容。在此示例中,我只是将数字写入文本区域。

public class FormMain extends JFrame {
    private JButton btnStart;
    private JPanel _panelTop, _panelMid, _panelBot;

    private PanelFoo panelFooA, panelFooB, panelFooC, panelFooD;

    private final List<String> ugsRj = Arrays.asList("AB");
    private final List<String> ugsMg = Arrays.asList("CD", "EF");
    private final List<String> ugsBA = Arrays.asList("GH", "IJ", "KL");
    private final List<String> ugsPE = Arrays.asList("MN", "OP", "RS", "TU");

    private void initialize() {
        this._panelTop = new JPanel();
        this._panelMid = new JPanel();
        this._panelBot = new JPanel();

        this.btnStart = new JButton("Start");
        this._panelBot.add(this.btnStart);

        this.panelFooA = new PanelFoo(this.ugsRj);
        this.panelFooB = new PanelFoo(this.ugsMg);
        this.panelFooC = new PanelFoo(this.ugsBA);
        this.panelFooD = new PanelFoo(this.ugsPE);
        _panelMid.setLayout(new BoxLayout(_panelMid, BoxLayout.X_AXIS));

        this._panelMid.add(this.panelFooA);
        this._panelMid.add(this.panelFooB);
        this._panelMid.add(this.panelFooC);
        this._panelMid.add(this.panelFooD);

    }

    public FormMain() {
        initialize();
        getContentPane().setLayout(new BorderLayout());
        setSize(800, 516);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(this._panelTop, BorderLayout.NORTH);
        getContentPane().add(this._panelMid, BorderLayout.CENTER);
        getContentPane().add(this._panelBot, BorderLayout.SOUTH);

        this.btnStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                final AuthenticationUser auth = new AuthenticationUser();
                auth.setUser("test");
                auth.setPassword("p@ss");
//
                final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        final WorkerDoSomething w1 = new WorkerDoSomething(panelFooA);
                        w1.addPropertyChangeListener(new ProgressListener(panelFooA.getProgressBar()));
                        final WorkerDoSomething w2 = new WorkerDoSomething(panelFooB);
                        w2.addPropertyChangeListener(new ProgressListener(panelFooB.getProgressBar()));
                        final WorkerDoSomething w3 = new WorkerDoSomething(panelFooC);
                        w3.addPropertyChangeListener(new ProgressListener(panelFooC.getProgressBar()));
                        final WorkerDoSomething w4 = new WorkerDoSomething(panelFooD);
                        w4.addPropertyChangeListener(new ProgressListener(panelFooD.getProgressBar()));

                        w1.execute();
                        w2.execute();
                        w3.execute();
                        w4.execute();

                        return null;
                    }

                };
                worker.execute();
            }
        });

    }
}

public class ProgressListener implements PropertyChangeListener {
    private JProgressBar bar;

    ProgressListener() {
    }

    ProgressListener(final JProgressBar b) {
        this.bar = b;
        this.bar.setValue(0);
    }

    @Override
    public void propertyChange(final PropertyChangeEvent evt) {
        // Determine whether the property is progress type
        if ("progress".equals(evt.getPropertyName())) {
            this.bar.setValue((int) evt.getNewValue());
        }
    }
}

public class PanelFoo extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = -1400188281877395934L;
    private JLabel label;
    private JTextArea textArea;
    private JScrollPane scrollPanel;
    private JProgressBar progressBar;

    public PanelFoo(final List<String> listOfStates) {
        setLayout(new FlowLayout());
        setSize(180, 400);
        final ImageIcon icon = createImageIcon("/images/waiting-list.png", "waiting start");
        this.label = new JLabel(listOfStates.get(0), icon, SwingConstants.HORIZONTAL);
        add(this.label);

        this.textArea = new JTextArea("Numbers: \n");
        this.textArea.setWrapStyleWord(true);
        this.scrollPanel = new JScrollPane(this.textArea);
        this.scrollPanel.setPreferredSize(new Dimension(150, 350));

        this.progressBar = new JProgressBar(0, 100);

        add(this.scrollPanel);
        add(this.progressBar);

        setVisible(true);
    }

    /** Returns an ImageIcon, or null if the path was invalid. */
    public ImageIcon createImageIcon(final String path, final String description) {
        if (path != null) {
            ImageIcon imageIcon = new ImageIcon(getClass().getResource(path));
            final Image image = imageIcon.getImage(); 
            final Image newimg = image.getScaledInstance(30, 30, Image.SCALE_SMOOTH);
            imageIcon = new ImageIcon(newimg, description);
            return imageIcon;

        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    public final JLabel getLabel() {
        return this.label;
    }

    public final void setLabel(final JLabel label) {
        this.label = label;
    }

    public final JTextArea getTextArea() {
        return this.textArea;
    }

    public final void setTextArea(final JTextArea textArea) {
        this.textArea = textArea;
    }

    public final JProgressBar getProgressBar() {
        return this.progressBar;
    }

    public final void setProgressBar(final JProgressBar progressBar) {
        this.progressBar = progressBar;
    }

}

public class WorkerDoSomething extends SwingWorker<Void, Void> {

    private JTextArea txtArea;
    private JLabel label;
    private Random r = new Random();

    WorkerDoSomething() {
    }

    public WorkerDoSomething(final PanelFoo panelFooInstance) {
        this.txtArea = panelFooInstance.getTextArea();
        this.label = panelFooInstance.getLabel();
    }

    private Integer randomInt(final int min, final int max) {
        final Integer randomNumber = this.r.nextInt((max - min) + 1) + min;

        return randomNumber;
    }

    @Override
    protected Void doInBackground() throws Exception {
        final Integer randomNumber = randomInt(10000000, 1000000000);
        long j;
        int progress = 0;
        final int onePerCent = randomNumber / 100;
        final int onePerMillion = onePerCent / 10;
        for (j = 0; j <= randomNumber; j++) {
            if (j % onePerCent == 0) {
                progress = (int) j / onePerCent;
                setProgress(progress);
            }
            if (j % onePerMillion == 0) {
                publish(j);
            }
            //Thread.sleep(randomInt(1000, 5000));
        }
        

        return null;
    }

    private void publish(final long num) {
        this.txtArea.append(num + "\n");
        this.txtArea.setCaretPosition(this.txtArea.getDocument().getLength());
    }

}

毕竟这是主要的 GUI:

Main Gui

这是执行:

Running without sleep

我只需要在每个 WorkerDoSomething 的任务上等待一段时间,添加该行(之前注释掉):Thread.sleep(randomInt(1000, 5000));

但是当我这样做时.. 整个执行会卡住,当然..因为它使用单个线程来运行所有任务 - 我想。

Running with sleep

有解决办法吗?

哦...业务上得用java 1.8:

java version "1.8.0_251"
Java(TM) SE Runtime Environment (build 1.8.0_251-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.251-b08, mixed mode)

整个项目在我个人git

---首先使用调试视角进行编辑

debug

最佳答案

执行不会卡住,因为 Swing 使用 10 个线程的线程池来运行 worker。
如果您注释掉这部分,您可以看到它正常工作:

if (j % onePerMillion == 0) {
    publish(j);
}

PS - 为什么要在 actionPerformed 方法中创建一个新的 SwingWorker?
为什么不简单地这样写:

    this.btnStart.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(final ActionEvent e) {
        final WorkerDoSomething w1 = new WorkerDoSomething(panelFooA);
        w1.addPropertyChangeListener(new ProgressListener(panelFooA.getProgressBar()));
        final WorkerDoSomething w2 = new WorkerDoSomething(panelFooB);
        w2.addPropertyChangeListener(new ProgressListener(panelFooB.getProgressBar()));
        final WorkerDoSomething w3 = new WorkerDoSomething(panelFooC);
        w3.addPropertyChangeListener(new ProgressListener(panelFooC.getProgressBar()));
        final WorkerDoSomething w4 = new WorkerDoSomething(panelFooD);
        w4.addPropertyChangeListener(new ProgressListener(panelFooD.getProgressBar()));

        w1.execute();
        w2.execute();
        w3.execute();
        w4.execute();
      }
    });

关于java - 使用 SwingWorker java 在线程池中等待任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63970091/

相关文章:

java - 如何让这个文本区域显示选择了哪些切换按钮?

java - 查找运行时间为 O(1) 的最小数字 - java

Java显示不同的对象

c# - ASP.NET/WCF : Why are logical/physical threads dropping on full GC cycle?

java - 将 JTextArea 复制为 "text/html"DataFlavor

java - 如何使用按钮按下操作在面板中显示图像

java - 使用 SharedPreferences 的最安全方式

java - 比较不同文件(CSV,Excel)Java Apache commons 和 poi 中两列的日期以了解日期相似的地方

java - 守护线程比普通线程轻吗?

java - 自动更新 UI