简体   繁体   中英

Threaded Java server with inner class and final variable

I've written the following code to implement a Threaded Server:

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

Now this seems to work, but in reflection I do not really understand what's going on with the final socket variable socket when the next connection arrives. How is each thread associated with the socket instance which was current when starting the thread? - is the final keyword responsible for that?

Think of it this way: socket is secretly passed as an argument to the new Runnable constructor, and it's kept as a variable in the anonymous Runnable class. (That's actually how it works, at the bytecode level.)

The created Runnable object contains a reference to the one specific Socket value at its creation time, so it can close that specific socket when it's done.

When passing a final variable to an anonymous inner class, that variable is effectively stored in the anonymous class as if it was an instance variable.

The code above could be effectively translated to:

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

Notice that making a local variable final is the only way to access it inside an anonymous inner class. See Jon's answer on " Why are only final variables accessible in anonymous class? " for details on the reasons.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM