私は、クラスがあるプロジェクトに取り組んでDeviceCommunicator
いimplements Runnable
ます。DeviceCommunicator
現在、メイン クラスは、(最終的に) ライブラリを使用してローカル ネットワーク上のデバイスに接続する単一のインスタンスをインスタンス化しSocket
ます。
最終的には、メッセージを送信する必要がある場合、のインスタンスがDeviceCommunicator
デバイスへのソケット接続を開き、メッセージを送信してから、新しいスレッドを開始して、次の行を介してソケットからデータを受信することを意味しますコード:
new Thread(new DeviceCommunicator()).start();
編集:明確にするために、これはプログラムが実行されたときの操作の順序です:
1) class は、次のようなコンストラクターをMAIN
使用してクラスをインスタンス化します。DeviceCommunicator
comm1 = DeviceCommunicator(hostName, portNum)
2)MAIN
クラスは にメッセージを送信したいので、次comm1
のように呼び出しますsend
。
comm1.send(someString)
3) comm1 はタイプであり、次のような hostName/portNum へDeviceCommunicator
の接続を開きます。Socket
deviceSocket = new Socket(hostName, portNum);
out = new PrintStream(deviceSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(deviceSocket.getInputStream()));
4) comm1someStr
は出力PrintStream
に送信し、次のコードでスレッドを初期化して応答をリッスンします。
new Thread(new DeviceCommunicator()).start();
リスニングスレッドにはコンストラクター引数がないため、出力変数と入力変数DeviceCommunicator
を作成する必要がありました。PrintStream
BufferedReader
static
のインスタンスが 1 つしかない場合、DeviceCommunicator
これはうまく機能します。
ただし、ローカルDeviceCommunicator
ネットワーク上の同じデバイスまたは異なるデバイスに接続できるクラスの複数のインスタンスが必要ですが、クラスの出力と入力が共有されているという事実を考慮すると (私は思う、私はJVM は、静的変数の変更が他の実行中のスレッドから見えるようになることを完全に保証していないことを読みました) - これは問題です!DeviceCommunicator
static
DeviceCommunicator
私はいくつかの調査を行いましたが、まったく同様のトピックに出くわしていません-ほとんどのトピックは基本的に「どちらかまたは」です。
A) トピックはスレッド化されたソケット通信に関するもので、静的変数を使用することで「ノンブロッキング」通信が実現されます。
また
B) implements Runnable
1 つのスレッドが 1 つの (通常は単純な) タスクを実行し、もう 1 つのスレッドが別の (通常はわずかに変更された) タスクを実行する単純なケースを考えます。
編集:提案される可能性のある解決策の1つは、単に入力BufferedReader
をリッスンDeviceCommunicator
スレッドに渡すことだと思いますが、送信されるメッセージのキューを実装しています(ネットワークに問題がある場合); そのため、メッセージを送信する必要がある場合は、キューの最初の要素を取得してソケット接続に出力し、リッスン スレッドで、メッセージがデバイスによって正しく受信されたことを確認したいと考えています。メッセージが正しく受信された場合は、キューから要素を削除したいと思いますが、これも問題を引き起こします.Javaでの変数の受け渡しは、参照ではなく常に値です! BufferedReader
したがって、入力とキューを渡すとしたら、リスニングで変更されていたキューDeviceCommunicator
DeviceCommunicator
メインインスタンスで変更する必要がある実際のキューではありません。
私が気付いていないこの問題の明白な解決策はありますか?
前もって感謝します!