4

これがどうなるかです。Javaアプリケーションのメインウィンドウ用のJFrameがあり、複数のJProgressBarを持つパネルが含まれています。JProgressBar ごとに別の Threads を独自に開始する Thread を開始したいと考えています。この「セカンダリ」スレッドのいずれかが終了したら、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();

2 つの問題。

  1. 上記のコードを実行すると、何も更新されませんでした。ec スレッドを開始するだけで、すべてがほぼ正常に機能します。

  2. 私は同期についてあまり知りませんし、すべての「プライマリ」スレッドを同時に開始するにはどうすればよいかわかりません。

手がかりはありますか?

4

2 に答える 2

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

    }

}
于 2012-10-18T22:50:06.097 に答える
1

ActivarBotonesスレッドは完了していません。

そのスレッドを実行していないときに機能する場合は、そのスレッドに何かが完了していません。そうしないと、EstablecerConexionesスレッドに到達します。このスレッドは開始後に呼び出すため.join()、そのスレッドが完了するまでコードは進みません。そのため、ブロックしている、またはループに陥っている何かがそこにあるに違いありません。

アプリケーションをデバッグ モードで実行し、ActivarBotonesスレッドにブレークポイントを設定します。それをトレースして、終了しない理由を確認してください。

2 番目の問題については、各メイン スレッドを開始しても、それらがすべて開始されるまで参加しない場合、それらはすべて同時に実行されます。もちろん、これは物事を大幅に単純化しすぎています。多くの人は、エグゼキュータ サービスを使用してスレッドを制御することを好みます。また、同期の問題が発生しないように、スレッドセーフな実装についても考慮する必要があります。最後に、Swing コンポーネントを操作している場合は、そのすべてを専用のイベント ディスパッチ スレッドで行う必要があります。

于 2012-10-18T14:59:54.817 に答える