私は、クラスがあるプロジェクト、DeviceCommunicator
、そのimplements Runnable
に取り組んでいます。現在、メインクラスは、Socket
ライブラリを使用して(最終的に)ローカルネットワーク上のデバイスに接続するDeviceCommunicator
という単一インスタンスをインスタンス化します。runnableを実装してソケットをオープンするクラスを複数回インスタンス化するにはどうすればいいですか?
最終的には、メッセージを送信する必要がある場合、DeviceCommunicator
のインスタンスがデバイスとのソケット接続を開き、メッセージを送信してからが新しいスレッドを開始し、
new Thread(new DeviceCommunicator()).start();
EDIT:次のコード行を介してソケット明確にするために、プログラムが実行されると、これは操作の順序である:
1)MAIN
クラスのようなコンストラクタ/ wのDeviceCommunicator
クラスをインスタンス化します。
comm1 = DeviceCommunicator(hostName, portNum)
2)MAIN
クラスがcomm1
にメッセージを送信したいので、それは次のようにsend
を呼び出します。
comm1.send(someString)
3)COMM1はタイプDeviceCommunicator
のものであり、ホスト名にSocket
接続を開きます/ portNumのように:
deviceSocket = new Socket(hostName, portNum);
out = new PrintStream(deviceSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(deviceSocket.getInputStream()));
4)COMM1が出力PrintStream
にsomeStr
を送信し、次のコードを使用して応答をリッスンするスレッドを初期化します
new Thread(new DeviceCommunicator()).start();
によりリスニングDeviceCommunicator
スレッドがコンストラクタの引数を持っていないという事実のために、それがいることを必要としました出力はPrintStream
、入力はBufferedReader
static
となります。
DeviceCommunicator
のインスタンスが1つしかない場合、これは素晴らしい動作です!
しかし、私はその後、同じまたはローカルネットワーク上の別のデバイスのいずれかに接続することができDeviceCommunicator
クラスの複数のインスタンスを好きしかしDeviceCommunicator
クラスの出力と入力がstatic
であるという事実を考慮しう彼らは共有されている(私は、のすべてのインスタンスにわたって静的な変数の変更が他の実行中のスレッドに見えることをJVMが保証していないと読んだことがあると思う - これは問題です!
私はいくつかの研究を行ってきたと私は非常に似てトピックに遭遇していない - ほとんどのトピックでは、基本的には「二者択一」です:
A)のトピックを、約ソケット通信を通され、ここで "非ブロッキング "通信は静的変数の使用によって達成される。他方は別の(典型的にはわずかに変更された)タスクを達成しながら、一つのスレッドは、一方(典型的には、単純な)タスクを達成する、請求
又は
B)単純implements Runnable
場合を考えます。
EDIT:提案されるかもしれない1つの解決策は、入力BufferedReader
をリスニングDeviceCommunicator
スレッドに単純に渡すことですが、送信するメッセージのキューを実装しています(ネットワークに問題がある場合)。したがって、メッセージを送信する必要がある場合は、キューの最初の要素を取得してソケット接続に出力するだけです。リスニングスレッドでは、メッセージがデバイスによって正しく受信されたことを確認します。メッセージが正しく受信された場合は、でも、キューから要素を削除したいと思いますが、が問題になります。Javaで変数を渡すことは、参照ではなく値によって行われます。したがって、入力BufferedReader
とをキューに渡す場合、リスニングDeviceCommunicator
で変更されていたキューは、メインのDeviceCommunicator
インスタンスで変更が必要な実際のキューにはなりません。
私にはわからないこの問題に対する明らかな解決策がありますか?
ありがとうございます!
あなたのクラスは 'DeviceCommunicator'ですか?ストリームに 'static'変数を使わなければならないのはなぜですか?私は新しいコンストラクタを追加できませんか? – Gray
はい、 'DeviceCommunicator'は、' Main'クラスによってインスタンス化されるクラスです。私はストリームに 'static'変数を使用することを考えました(これはすでに説明されていると思っていましたので、教えてください)。 'Socket'接続を作成するときに設定されたメインの' DeviceCommunicator'と同じ入力 'BufferedReader'です。私は何かをクリアすることができるかどうかを確認するコードをいくつか追加します。 – MandM
Javaは常に「値渡し」ですが、誤解を招くことです。引数が(キューのような)オブジェクトの場合、呼び出し元と呼び出し先の両方が同じオブジェクトへの参照を持ちます。すべてのキュー操作は、両方のスレッドから見えます。 – Gray