4

を学び、SwingWorker質問があります
(私はこれに対する答えを探していますが、この設定に具体的に対処していません)

最大同時2〜3接続のみを持つ小さなサーバーを作成しています。内部クラスを持つ
を使用していますJframeSwingWorker

SwingWorkerでdoInBackground()私は持っています:

while(true) {
  Socket client_socket = listen_socket.accept();
  Connection con = new Connection(client_socket, "name");
  Future<Connection> future = es.submit(con , con ); 
  tasks.add(future);
 }

Connectionrunnableあり、のサブクラスとして宣言されていSwingWorkerます。

が完了する前runnableに、SQLにエントリを書き込みます。
次に、この実行可能ファイルが死ぬ前に、Jframeイベントディスパッチスレッドにヘッズアップを送信するにはどうすればよいでしょうか。
そして、JframeSQLで新しいエントリをチェックし、ユーザーに表示します。

何をするのが最善か:

Jframe1-実行可能なすべてのユーザーがイベントディスパッチスレッド にメッセージを送信できるインターフェイスウィッチを作成します。

2-すべての新しい接続にSwingWorkerinstedofを使用し、サーバーでメソッドを呼び出し、そのメソッドを使用してメソッドを呼び出すrunnablesDone()SwingWorkerJframeEventQueue.invokeLater..

3-またはPropertyChangeListenerを使用します(どういうわけかわかりません)

4-各ランナブルに参照と実行を許可しJframeますEventQueue.invokeLater..

4

3 に答える 3

1

バックグラウンド ワーカー スレッドを生成する SwingWorker の例を作成しようとしました。その結果は、固定プールの ExecutorService と CompletionService を介して公開されます。1 つのスレッド内でワーカー スレッドを作成し、別のスレッド (SwingWorker バックグラウンド スレッド) 内でその先物に対して get を呼び出すスレッド セーフに関して、まだいくつか質問があります。

例えば:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.swing.*;

@SuppressWarnings("serial")
public class TestSwingWorker extends JPanel {
   public static final int POOL_SIZE = 4;
   private JTextArea tArea = new JTextArea(10, 30);
   private JButton doItBtn;

   public TestSwingWorker() {
      doItBtn = new JButton(new AbstractAction("Do It!") {
         public void actionPerformed(ActionEvent ae) {
            swingWorkerRunning(true);
            MySwingWorker mySW = new MySwingWorker();
            mySW.execute();
            tArea.append("SwingWorker started\n");
         }
      });
      JPanel btnPanel = new JPanel();
      btnPanel.add(doItBtn);
      tArea.setEditable(false);
      tArea.setFocusable(false);

      setLayout(new BorderLayout());
      add(new JScrollPane(tArea), BorderLayout.CENTER);
      add(btnPanel, BorderLayout.SOUTH);
   }

   private class MySwingWorker extends SwingWorker<String, String> {
      @Override
      protected String doInBackground() throws Exception {
         ExecutorService execService = Executors.newFixedThreadPool(POOL_SIZE);
         final CompletionService<String> completionService = new ExecutorCompletionService<String>(
               execService);
         new Thread(new Runnable() {

            @Override
            public void run() {
               for (int i = 0; i < POOL_SIZE; i++) {
                  final int index = i;
                  completionService.submit(new Callable<String>() {
                     public String call() throws Exception {
                        Thread.sleep(2000 * index + 500);
                        return "Callable " + index + " complete";
                     }
                  });
                  try {
                     Thread.sleep(1000);
                  } catch (InterruptedException e) {
                  }
               }
            }
         }).start();

         for (int i = 0; i < POOL_SIZE; i++) {
            Future<String> f = completionService.take();
            publish(f.get());
         }

         return "Do in background done";
      }

      @Override
      protected void process(List<String> chunks) {
         for (String chunk : chunks) {
            tArea.append(chunk + "\n");
         }
      }

      @Override
      protected void done() {
         try {
            tArea.append(get() + "\n");
         } catch (InterruptedException e) {
            e.printStackTrace();
         } catch (ExecutionException e) {
            e.printStackTrace();
         } finally {
            swingWorkerRunning(false);
         }
      }
   }

   public void swingWorkerRunning(boolean running) {
      doItBtn.setEnabled(!running);
   }

   private static void createAndShowGui() {
      TestSwingWorker mainPanel = new TestSwingWorker();

      JFrame frame = new JFrame("TestSwingWorker");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

訂正大歓迎です!

于 2011-11-24T17:43:24.303 に答える
1

SwingWorkerドキュメントはかなり明確です。SwingWorkerメソッドで長いタスクをサブクラス化して実行する必要がありますdoInBackground()done()メソッドの UI を更新する必要があります。

それは本当に簡単です。

編集:
より明確にするために。Connectionクラスが拡張されていると仮定すると、SwingWorkerそれを実装する必要はなくRunnable、ワーカーを実行するためのスレッド プールを明示的に提供する必要もありませrun()。メソッドの内容を に入れるだけdoInBackground()です。

これで、メイン ループは次のようになります。

while (true) {
  Socket client_socket = listen_socket.accept();
  Connection con = new Connection(client_socket, "name");
  con.execute();
}

ExecutorServiceメインループでに送信しているようです。これには特定の理由がありますか (aはワーカー スレッドSwingWorkerの独自の内部を管理することに注意してください)。ThreadPoolExecutor同時クライアント数を制限するためですか? もしそうなら、これを達成する他の方法があります。

于 2011-11-24T14:08:49.560 に答える
1

私なら次のようにします: ワーカー スレッドに渡されるスレッド セーフなブロック キューまたはリストを親スレッドに配置します。タスクが完了すると、ワーカー スレッドは結果エントリ ID を含むメッセージをこのブロッキング キューにポストします。親スレッドは、子スレッドからの結果を待つキューでブロックされます。キューに要素があるときはいつでも、親スレッドはそれを受け取り、DB からそのデータを取得してユーザーに表示します。

于 2011-11-24T14:05:16.113 に答える