基本的に、私はグラフィカルなスイングアプリケーションを持っています。UDP を使用してデータを送受信する必要がありますが、アプリケーションのコードで受信 (パケット) 呼び出しを行いたくありません。プログラムの受信側を別のスレッドで実行することにしました。スレッドには、着信パケットの値に更新される int フィールドがあります。スレッドからこのフィールドの値を取得するにはどうすればよいですか。フィールドの get メソッドを呼び出すだけでよいですか、それとも最初にスレッドを中断する必要がありますか?
3 に答える
GUI スレッドは int ゲッターを安全に読み取ることができますが (適切な同期または volatile 変数を想定)、時間をかけてSwingWorkerを使用することを検討してください。これにより、アプリの応答性が向上します。基本的に、カスタム スレッドを SwingWorker オブジェクトに置き換えます。今持っているコードは にrun()
入りSwingWorker.doInBackground()
ます。
ワーカーを開始すると、doInBackground
コードが別のスレッドで実行されます。おそらく、これは UDP 受信ループです。ループが新しい int を受け取ると、publish
(まだバックグラウンド スレッドで) 呼び出します。これにより、別の SwingWorker メソッドprocess
(カスタム コードでオーバーライドしたもの) がイベント スレッドで呼び出されます。ここでは、イベント スレッドで実行しているため、GUI を安全に更新できます。
これにより、UDP スレッドの getter をポーリングするためのタイマーを作成する必要がなくなります。受信 -> 発行 -> プロセス シーケンスが非常に高速であるため、UI の応答性が向上します。
ここには1つの目的しかありません。UIは、ネットワーク上のデータを待ってハングするべきではありません。LinkedListオブジェクトに通知するdataJustArrivedメソッドであるLinkedList(ArrayListではない)が必要です。しばらくの間(true)実行され、LinkedListを待機しているスレッド。
dataJustArrivedは、データオブジェクトをリンクリストに追加し、待機を通知します。待機はロックを解除し、linkedList.lenght> 0かどうかを確認し、リストからデータを削除して(GETSではなく、削除します)、UIを処理します。
重要なポイント
- 追加と待機は同期された(dataList)コードブロックにある必要があります
- addLastとremoveFirst
- 削除し、getを使用しないでください
- LinkedListは機能しますが、ArrayListは機能しません(非常にコストのかかる操作になります)
- ロックが解除されるのを待った後、dataList.length>0を確認します
待つ前に、dataList.lenght> 0かどうかを確認してください。正しく処理するデータがある場合は、なぜ待つのでしょうか。
public synchronized void dataJustArrived(Object data) { synchronized (dataList) { dataList.addLast(data); this.notify(); } } public void run() { Object data ; while (true) { synchronized (this) { if (dataList.isEmpty()) { try { dataList.wait(); } catch (InterruptedException ignored) { ignored.printStackTrace(); } } if (!dataList.isEmpty) data = dataList.removeFirst(); // // Process your UI here // } } }
パケット レシーバー スレッド クラスの着信パケット数フィールドで、同期された getter メソッドを作成する必要があります。
概念に関する簡単なチュートリアルについては、このページを参照してください。