2012-06-04 45 views
1

我想創建一個連續的線程,其中服務器從客戶端接收/發送消息,但是當我嘗試檢查下一個元素時,它會卡住:如何繞過掃描儀檢查下一個元素(如果有道理)

public void run() 
{ 
    try 
    { 
     try 
     { 
      ArrayList<Socket> connections = parent.getConnections(); 
      in = new Scanner(socket.getInputStream()); 

      while(true) 
      { 
       if(in.hasNextLine()) // Gets stuck here 
       { 
        String message = in.nextLine(); 
        System.out.println("Client said " + message); 
       } 
      } 
     } 

     finally 
     { 
      socket.close(); 
     } 
    } 

    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 

如何使循環不會卡在指定點

+1

定義'卡住'。套接字是否允許異步通信?你內在的「catch」條款在哪裏,或者說有什麼意義?不要一攬子捕捉所有例外情況 - 只能捕捉那些可以說明的情況(應用程序的最高級別除外)。不要使用'while(true)' - 檢查一些條件,這樣可以安全地關閉循環;目前用戶需要通過某種線程管理器(比如TaskManager)來終止線程,這不是一個愉快的前景。 –

+0

通過卡住我的意思是它不會完成循環,並等待流的輸出。只有在客戶端輸出時,循環纔會完成。我已經修復了try/catch語句,while(true)循環不是問題。 – mudassir

+0

這表明從'socket.getInputStream()'返回的流是'阻塞' - 也就是說,它等待輸入。您可能需要執行以下操作之一:1)將最初接收到的流包裝成不會阻塞的流2)爲套接字設置「TIMEOUT」選項(並捕獲產生的異常)3)使用線程和隊列,你的程序的其餘部分可以繼續,而不管輸入套接字的狀態如何(這可能是最好的選擇,並且可以與其他結合起來)。 –

回答

1

假設你希望能夠對付「行」,我可能會像這樣的東西開始:

public class SocketReader implements Runnable { 

    private final InputStream stream; 
    private final Queue<String> destination; 
    private volatile boolean active = true; 

    private SocketReader(InputStream stream, Queue<String> destination) { 
     this.stream = stream; 
     this.destination = destination; 
    } 

    public static SocketReader getReader(Socket toRead, Queue<String> destination) throws IOException { 
     return new SocketReader(toRead.getInputStream(), destination); 
    } 

    public void shutdown() { 
     active = false; 
    } 

    public void run() { 
     while(active) { 
      if (stream.hasNextLine() && active) { 
       final String line = stream.nextLine; 
       destination.add(line); 
      } 
     } 
     try { 
      stream.close(); 
     } catch (IOException e) { 
      // Log somewhere 
     } 
    } 
} 

將它放到它自己的線程中(或者作爲線程或執行程序池的一部分,實際上),並且使應用程序的其餘部分對於此代碼無阻塞。 預計這將阻止等待從stream.hasNextLine()更新。如果您不希望主動輪詢隊列,但以其他方式處理更新,則甚至可以提供BlockingQueue

然後你可以做這樣的事情的輸出:

public class QueuedPrinter implements Runnable { 

    private final Queue<String> input; 
    private final PrintStream destination; 
    private volatile boolean active; 

    public QueuedPrinter(Queue<String> input, PrintStream destination) { 
     this.input = input; 
     this.destination = destination; 
    } 

    public void shutdown() { 
     active = false; 
    } 

    public void run() { 
     while(active) { 
      final String line = input.poll(); 
      if (line != null && active) { 
       destination.println(line); 
      } 
     } 
    } 

} 

請注意,我沒有測試過這一點,你可能要稍微調整一下事情經過其他異常。您可能需要添加額外的錯誤檢查代碼(想到空處理)。此外,這不是完全線程安全,但對於大多數用途可能是'夠用'。

+0

非常感謝!這實際上有很大幫助。對不起,遲到的回覆,我一直在專注。 – mudassir