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();
}

现在这似乎可行,但经过反思,我并不真正了解下一个连接到达时最终套接字变量套接字发生了什么。每个线程如何与启动线程时当前的套接字实例相关联?- final关键字对此负责吗?

4

2 回答 2

3

可以这样想:socket作为参数秘密传递给new Runnable构造函数,并作为变量保存在匿名Runnable类中。(这实际上是它的工作原理,在字节码级别。)

创建的Runnable对象在其创建时包含对一个特定Socket值的引用,因此它可以在完成后关闭该特定套接字。

于 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 回答