2

スレッドサーバーを実装するために、次のコードを記述しました。

ServerSocket passiveSocket = new ServerSocket(port, maxConnections);  
while(true){
  final Socket socket = passiveSocket.accept();                       
  new Thread(new Runnable() {
      public void run() {
          //access socket as needed to communicate. E.g.:
          PrintWriter writer = new PrintWriter(socket.getOutputStream());
          //Finally close socket.
          socket.close();
      }
  }).start();
}

これでうまくいくように見えますが、振り返ってみると、次の接続が到着したときに最後のソケット可変ソケットで何が起こっているのかがよくわかりません。各スレッドは、スレッドの開始時に最新だったソケットインスタンスにどのように関連付けられていますか?-最後のキーワードがその原因ですか?

4

2 に答える 2

3

このように考えてください。コンストラクターsocketへの引数として密かに渡されnew Runnable、匿名Runnableクラスの変数として保持されます。(これが、バイトコードレベルでの実際の動作です。)

作成されたRunnableオブジェクトには、Socket作成時に1つの特定の値への参照が含まれているため、作成が完了すると、その特定のソケットを閉じることができます。

于 2012-04-17T16:23:58.050 に答える
2

final変数を匿名の内部クラスに渡す場合、その変数は、インスタンス変数であるかのように匿名クラスに効果的に格納されます。

上記のコードは、効果的に次のように変換できます。

private static final class RunnableAnonSubclass implements Runnable {
    private final Socket socket; 
    private RunnableAnonSubclass (Object socket) {
        this.socket = socket;
    }

    public void run() {
        //access socket as needed to communicate. E.g.:
        PrintWriter writer = new PrintWriter(socket.getOutputStream());
        //Finally close socket.
        socket.close();
    }
}

// ... 
{ 
    ServerSocket passiveSocket = new ServerSocket(port, maxConnections);  
    while(true){
        Socket socket = passiveSocket.accept();               
        new Thread(new RunnableAnonSubclass(socket)).start();
    }
}

ローカル変数を作成するfinalことが、匿名の内部クラス内でそれにアクセスする唯一の方法であることに注意してください。理由の詳細については、「匿名クラスで最終変数のみにアクセスできるのはなぜですか? 」に関するJonの回答を参照してください。

于 2012-04-17T16:24:06.890 に答える