2012-04-17 52 views
2

我已經寫了下面的代碼來實現線程服務器:線程Java服務器內部類和最後一個變量

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

現在,這似乎工作,但細想我真的不明白是怎麼回事當下一個連接到達時,最後的套接字變量套接字。每個線程如何與啓動線程時當前的套接字實例關聯? - 最後是這個關鍵字是誰負責的?

回答

3

想想這樣:socket作爲參數偷偷傳遞給new Runnable構造函數,並且它在匿名Runnable類中保留爲變量。 (在字節碼級別,實際上它是如何工作的。)

創建的Runnable對象在其創建時包含對特定Socket值的引用,因此它可以在完成時關閉該特定套接字。

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是訪問它匿名內部類內的唯一途徑。有關原因的詳細信息,請參閱「Why are only final variables accessible in anonymous class?」上的Jon's answer