Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top