2011-04-14 149 views
1

我正在實現一個非常基本的API來更好地控制ServerSocket和套接字,但是由於我缺乏線程知識,我處於一個非常奇怪的問題,無法修復。讓我解釋一下。停止ServerSocket accept()循環線程

在我的SocketStreamReceiver類中,我使用輔助線程來偵聽帶有ServerSocket#accept()的新套接字。有兩種方法:客戶端可以使用start()和stop()來啓動(創建一個線程並開始用accept()進行偵聽),並停止(關閉ServerSocket並銷燬線程)SocketStreamReceiver。

你將如何實現stop()方法?請記住,stop()可以在由start()啓動的相同輔助線程中的doSomething()內調用。你可以改變你想要的任何東西:你可以在while(running)之前,在線程內創建ServerSocket。

public class SocketStreamReceiver{ 
    ... 
    private Thread thread; 
    private ServerSocket server; 
    private boolean running; 
    ... 

    public void start() throws IOException{ 
     if (thread != null) return; 

     server = new ServerSocket (port); 
     thread = new Thread (new Runnable(){ 
      @Override 
      public void run(){ 
       try{ 
        while (running){ 
         Socket socket = server.accept(); 
         doSomething (socket); 
        } 
       }catch (SocketException e){ 
        ... 
       }catch (IOException e){ 
        ... 
       } 
      } 
     }, "SocketStreamReceiver"); 
     thread.start(); 
    } 

    public void stop() throws IOException{ 
     if (thread == null) return; 

     //code... 

     thread = null; 
    } 
} 

謝謝。

編輯 - 解決方案:

public class SocketStreamReceiver{ 
    private Thread thread; 
    private ServerSocket server; 
    private volatile boolean running; 
    ... 

    public synchronized void start() throws IOException{ 
     if (thread != null) throw new IllegalStateException ("The receiver is already started."); 

     server = new ServerSocket (port); 
     thread = new Thread (new Runnable(){ 
      @Override 
      public void run(){ 
       try{ 
        running = true; 
        while (running){ 
         doSomething (server.accept()); 
         ... 
        } 
       }catch (SocketException e){ 
        ... 
       }catch (IOException e){ 
        ... 
       } 
      } 
     }, "SocketStreamReceiver"); 
     thread.start(); 
    } 

    public synchronized void stop(){ 
     if (thread == null) return; 

     running = false; 
     try{ 
      if (server != null){ 
       server.close(); 
      } 
     }catch (IOException e){} 

     thread = null; 
    } 
} 

回答

2

我只想做

public void stop() { 
    running = false; 
    try{ 
     if (server != null) server.close(); 
    } catch (IOException ignored){ 
    } 
} 

它不會出現,你甚至需要運行的標誌。不過,我會在您的服務器接受代碼中使用它來確定是否預期有異常。即當運行== false時忽略所有異常。

我會使running易變。

如果你可以從不同的線程運行這些,我會讓start()/ stop()同步。

+1

如果server.close()被調用並且在我們做了server.accept()之後會發生什麼? ServerSocket是否阻塞該線程? – 2011-04-14 08:43:01

+2

accept()會拋出一個SocketException,無論如何你必須捕獲它。 – 2011-04-14 08:51:43

+1

爲什麼你捕捉異常並拋出它? – MByD 2011-04-14 08:59:22