2011-12-03 15 views
2

Javaでマルチスレッドプログラムを作成しています。ここでは、新しいクライアント接続を処理するために別のスレッドを作成しています。私持っている:私は持っているClientHandlerのスレッドでJavaのサーバープログラムでSocketオブジェクトへの参照を渡す

Socket s; 


while(true) 
{ 
    s = server.accept(); 
    ClientHandler ch = new ClientHandler(s); 
    Thread servingThread = new Thread(ch); 
    servingThread.start(); 
} 

public class ClientHandler implements Runnable 
{ 
    private Socket s; 

public ClientHandler(Socket _Socket, boolean _accepted, BaseStation _bs) 
{ 
    this.s = _Socket; 
} 

をJavaで私は、オブジェクトが、それへの参照のみを渡すことができない場合は、それが問題を引き起こすことが起こっていませんserverが新しい接続を受け入れるたびに、ClientHandler内のsインスタンスに接続しますか? ClientHandlerの内部でも変更されず、破損しますか?もしそうなら、正しい方法は何ですか?

答えて

2

Socketオブジェクト(Javaの他のオブジェクトと同様)は参照によって渡されるため、異なるモジュールまたは異なるスレッドによって参照される可能性があり、予測できない動作を引き起こす可能性があります。

ただし、プログラムの場合は問題ありません。理由は:サーバーが新しい接続を受け入れるたびに、新しいSocketというオブジェクトが作成され、の新しいのインスタンスClientHandlerに渡されます。したがって、クライアントからの新しい接続はすべて、独立したClientHandlerインスタンスによって提供されるため、Socketオブジェクトが心配する競合条件は存在しません。あなたは今のところ安全です。反例として

あなたはこのような同じSocketオブジェクトから読み取るための2つのClientHandlerスレッドを作成することにした場合...

s = server.accept(); 
ClientHandler ch = new ClientHandler(s); 
ClientHandler ch2 = new ClientHandler(s); 
new Thread(ch).start(); 
new Thread(ch2).start(); 

... 2つのClientHandler sが同じSocketオブジェクトへ同じの参照を取得し、両方の試みは、同じソケットから読み取る場合、彼らはそれぞれが半分だけを取得しますので、あなたはトラブルになる可能性がありますデータの例えば。文字列"hello"を受け取った場合は、chと表示され、"hel"ch2と表示され、"lo"と表示されます。

1

少し混乱しますが、コードは表示されているとおりに動作するはずです。 Javaは最初に値渡しされ、次に参照渡しされます。 I.E.では、 "Socket s"へのポインタを渡すのではなく、実際の値 "s"を渡しています。

混乱を避けるため、「Socket s;」という宣言を削除し、ループの最初の行を「Socket s = server.accept();」にします。

+1

normalocity - http://stackoverflow.com/questions/589919/does-java-pass-by-reference、http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526 -pass.htmlなど、Javaが最初に値渡しすることを確認します。 – ziesemer

+0

正確には、Javaはまず値で渡され、次に参照によって渡されます。 :-) – ziesemer

+0

値で解決される「コンテナ」を渡して、実際の参照として値を維持して、参照渡しを強制することができます。 I.E.、Socket [] socketHolder =新しいソケット[1]; socketHolder [0] = sです。 OPが単純に "s"ではなくsocketHolder [0]を使用した場合、彼は実際には参照によってソケットを渡してしまい、問題が発生します。 – ziesemer

2

説明するにはIs Java "pass-by-reference" or "pass-by-value"?を参照してください。 ClientHandlerSocketインスタンスのコピーに影響を与えていないローカル変数sの値に変更 - 各ClientHandlerは独自のSocketを持っているため、新しいClientHandlerインスタンスに新しいSocketインスタンスを渡す

は大丈夫です。同じ基本Socketオブジェクトインスタンスに

ClientHandler ch = new ClientHandler(s); 
Thread servingThread = new Thread(ch); 
servingThread.start(); 

s.someMethod(); // close, read etc. 

ch.ssので、両方のポイント:このよう

何かが問題を引き起こします。

ところで、新しいスレッド全体をwhileループで回転させるのは、それらのスレッドが終了することが確実でない限り、おそらく悪いです。おそらくThreadPoolを使うほうが良いでしょう。

関連する問題