複数の SwingWorkers を待機しています
SwingWorker は、バックグラウンド タスクを実行し、ワーカー スレッドから GUI を更新する便利な方法です。ただし、複数の SwingWorker インスタンスが同時に実行され、それらの完了を調整する必要がある場合があります。
複数の SwingWorker がループ内で作成および実行される次のコードを考えてみましょう。
import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.InvocationTargetException; import javax.swing.*; public class TestApplet extends JApplet { @Override public void init() { try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); } }); } catch (InterruptedException | InvocationTargetException ex) { } } private void createGUI() { getContentPane().setLayout(new FlowLayout()); JButton startButton = new JButton("Do work"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { for (int i = 0; i < 10; i++) { new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { // Do some work return null; } }.execute(); } } }); getContentPane().add(startButton); } }
「作業を実行」ボタンをクリックすると、10 個の SwingWorker インスタンスが作成され、実行されます。各 SwingWorker はバックグラウンドでいくつかの作業を実行し、作業が完了すると GUI を更新します。ただし、SwingWorkers 間には調整がありません。つまり、SwingWorkers は任意の順序で完了する可能性があり、特に基になるタスクにかかる時間が異なる場合、GUI が不規則に更新される可能性があります。
GUI を確実に更新するには一貫性のある予測可能な方法で、SwingWorkers の完了を調整することが重要です。これを実現するにはいくつかのアプローチが使用できますが、最も適切なアプローチはアプリケーションの特定の要件によって異なります。
1.バリア
バリアは、複数のスレッドがすべてのスレッドが共通点に到達するまで待機できるようにする同期メカニズムです。 SwingWorkers のコンテキストでは、バリアを使用して、次のようにすることで、すべての SwingWorker がタスクを完了した後にのみ GUI が更新されるようにすることができます。
import java.lang.reflect.InvocationTargetException; import java.util.concurrent.*; import javax.swing.*; public class TestApplet extends JApplet { private static final int NUM_WORKERS = 10; private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(NUM_WORKERS); private static final CyclicBarrier BARRIER = new CyclicBarrier(NUM_WORKERS, new Runnable() { @Override public void run() { // All SwingWorkers have completed, update the GUI } }); @Override public void init() { try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); } }); } catch (InterruptedException | InvocationTargetException ex) { } } private void createGUI() { JButton startButton = new JButton("Do work"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { for (int i = 0; i < NUM_WORKERS; i++) { EXECUTOR.submit(new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { // Do some work return null; } @Override protected void done() { BARRIER.await(); } }); } } }); getContentPane().add(startButton); } }
このアプローチでは、SwingWorkers はタスクを同時に実行し、 Java 仮想マシン (JVM) はスレッド プールを管理し、タスクの実行をスケジュールします。すべての SwingWorker がタスクを完了すると、バリアがトリガーされ、GUI の更新を担当するバリアの run() メソッドが実行されます。
2. CountDownLatch
CountDownLatch は、特定の数のイベントが発生するまで複数のスレッドを待機できるようにするもう 1 つの同期メカニズムです。 SwingWorkers のコンテキストでは、次のように CountDownLatch を使用して、すべての SwingWorker がタスクを完了した後にのみ GUI が更新されるようにすることができます。
import java.lang.reflect.InvocationTargetException; import java.util.concurrent.*; import javax.swing.*; public class TestApplet extends JApplet { private static final int NUM_WORKERS = 10; private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(NUM_WORKERS); private static final CountDownLatch LATCH = new CountDownLatch(NUM_WORKERS); @Override public void init() { try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); } }); } catch (InterruptedException | InvocationTargetException ex) { } } private void createGUI() { JButton startButton = new JButton("Do work"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { for (int i = 0; i < NUM_WORKERS; i++) { EXECUTOR.submit(new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { // Do some work return null; } @Override protected void done() { LATCH.countDown(); } }); } } }); getContentPane().add(startButton); } private void updateGUI() { // Update the GUI } @Override public void run() { try { LATCH.await(); updateGUI(); } catch (InterruptedException ex) { } } }
このアプローチでは、SwingWorkers がタスクを実行します。同時に実行され、JVM はスレッド プールを管理し、タスクの実行をスケジュールします。すべての SwingWorker がタスクを完了すると、ラッチ カウントが 0 に達し、アプレットの run() メソッドが実行を継続して GUI を更新できるようになります。
3.フェイザー
フェイザーは同期です
以上が複数の同時実行 SwingWorkers の完了を調整するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。