繁体   English   中英

JFrame调用多个并发线程来更新调用者JFrame中的JProgressBar

[英]JFrame calling multiple concurrent Threads that updates a JProgressBar in the caller JFrame

事情就是这样:我有一个Java应用程序主窗口的JFrame,它包含一个包含多个JProgressBar的面板。 我想为每个JProgressBar启动一个Thread,它将自己启动另一个Threads。 当任何这个“辅助”线程完成时,我想在我的JFrame中更新JProgressBar。 此外,在安排所有这些之前,因为我不希望用户能够点击JFrame上的任何内容,我还想在JFrame中设置一些按钮的setEnabled(false)。 简单?

ActivarBotones abFalse = new ActivarBotones(false);
abFalse.start();
try {
    abFalse.join();
} catch (InterruptedException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

EstablecerConexiones ec = new EstablecerConexiones();
ec.start();
try {
    ec.join();
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

ActivarBotones abTrue = new ActivarBotones(true);
abTrue.start();

两个问题。

  1. 如果我从上面运行代码,没有任何更新。 如果我只启动ec线程,一切都能正常工作。

  2. 我不太了解同步,也不知道我应该怎么做才能同时启动所有“主”线程。

有线索吗?

这是一个小样本,我不认为它回答了你所有的问题,但它展示了基本的概念(有一个生病的妻子和照顾一个6个月大的孩子,用一只手打字:P)

public class ThreadedProgress {

    public static void main(String[] args) {
        new ThreadedProgress();
    }

    public ThreadedProgress() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JPanel progressPane = new JPanel(new GridBagLayout());
                JProgressBar progressBar = new JProgressBar(0, 100);
                progressPane.add(progressBar);

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(progressPane);
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                new Thread(new MainThread(progressBar)).start();

            }

        });
    }

    public interface CallBack {
        public void done(Runnable runnable);
    }

    public static class MainThread implements CallBack, Runnable {

        public static final Object UPDATE_LOCK = new Object();
        public static final Object WAIT_LOCK = new Object();
        private List<Runnable> running = new ArrayList<>(25);
        private List<Runnable> completed = new ArrayList<>(25);
        private final JProgressBar progressBar;

        public MainThread(JProgressBar progressBar) {
            this.progressBar = progressBar;
        }

        @Override
        public void done(Runnable runnable) {
            synchronized (UPDATE_LOCK) {
                running.remove(runnable);
                completed.add(runnable);
            }
            int count = running.size() + completed.size();
            updateProgress(completed.size(), count);
            synchronized (WAIT_LOCK) {
                WAIT_LOCK.notify();
            }
        }

        protected void updateProgress(final int value, final int count) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    int progress = Math.round(((float) value / (float) count) * 100f);
                    progressBar.setValue(progress);
                }
            });
        }

        @Override
        public void run() {
            for (int index = 0; index < 5; index++) {
                ChildSpawn spawn = new ChildSpawn(this);
                running.add(spawn);
            }
            for (Runnable runnable : running) {
                new Thread(runnable).start();
            }

            while (running.size() > 0) {
                synchronized (WAIT_LOCK) {
                    try {
                        WAIT_LOCK.wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }
            System.out.println("I'm all done");
        }
    }

    public static class ChildSpawn implements Runnable {

        private CallBack callBack;

        public ChildSpawn(CallBack callBack) {
            this.callBack = callBack;
        }

        @Override
        public void run() {
            try {
                Thread.sleep((long)Math.round(Math.random() * 5000));
            } catch (InterruptedException ex) {
            }

            callBack.done(this);            
        }

    }

}

ActivarBotones线程未完成。

如果它在你没有运行该线程时有效,那么该线程中的某些东西没有完成。 否则,它将通过EstablecerConexiones线程。 由于在启动它之后在此线程上调用.join() ,因此在该线程完成之前代码将不会继续。 所以必须有一些东西阻塞或陷入循环。

以调试模式运行应用程序并在ActivarBotones线程中放置一个断点。 追踪它,看看它为什么没有完成。

对于您的第二个问题,如果您启动每个主线程但在它们全部启动之前不加入它们,它们将同时运行。 当然,这大大超出了事情的范畴。 许多人更喜欢使用执行器服务来控制他们的线程。 您还必须担心线程安全实现,因此不会遇到同步问题。 最后,如果您正在与Swing组件进行交互,那么所有这些都需要在专用的Event Dispatch Thread上完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM