Threaded Java server with inner class and final variable
-
01-06-2021 - |
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?
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.