2011-11-21 58 views
2

我正在從套接字讀取消息(通過TCP協議),但我注意到CPU花了很多時間調用BufferedInputStream的available()方法。這是我的代碼:BufferedInputStream available()吃CPU

@Override 
public void run() 
{ 

    Socket socket; 
    Scanner scanner; 
    BufferedInputStream buffer = null; 

    try 
    { 
     socket = new Socket(SERVER_HOST, SERVER_PORT); 

     System.out.println("Connection Completed"); 

     InputStream inputStream = socket.getInputStream(); 
     buffer = new BufferedInputStream(inputStream); 

     StringBuilder readCharacter; 

     while (true) 
     { 

      readCharacter = new StringBuilder(); 
      try 
      { 

       while (buffer.available() > 0) 
       { 
        readCharacter.append((char) buffer.read()); 
       } 

      } 
      catch (IOException e) 
      { 
       e.printStackTrace(); 
       buffer.close(); 
      } 

      String array[] = separe(new String(readCharacter)); 
     ... //parsing the message 

我也試着使用int read=buffer.read()和檢查if (read!=-1)而不是使用現有的功能,但在這種情況下,我不能夠識別郵件的末尾...在我的StringBuilder的'readCharacter'我有一個以上的消息,一個接一個..它導致我的解析過程失敗...

而不是使用available()檢查,到readCharacter我只有一個消息在一段時間..和解析工程...

你能幫我理解爲什麼,以及如何避免是否吃CPU?

+0

那麼,嘗試使用.read()方法解析while循環。 – nullpotent

+0

嗨你的意思是保持available()檢查或使用read()!= - 1?然而,我已經嘗試了兩種方法,但它們不起作用 – marco

+2

有一個常見的誤解,你可以暗示消息開始和結束時數據之間的暫停。您不能發送字節流的消息,只能發送字節。您只能通過閱讀內容來確定消息何時開始和結束。 –

回答

3

這個循環:

while (buffer.available() > 0) 
    { 
    readCharacter.append((char) buffer.read()); 
    } 

可以通過簡單的更換:

readCharacter.append((char) buffer.read()); 

而不是調用無阻塞available()一遍又一遍(這會消耗大量的CPU)的就叫read()這將阻止不消耗CPU,直到有可用的東西。看起來這是你想用更少的代碼和複雜性實現的。

+0

問題是,如果我刪除了這段時間,我讀了一個字符,並且只傳遞了一個字符到我的解析器。 – marco

+0

@marco:現在我發現你的代碼通常被破壞了(另請參閱Peter Lawreys對你的問題的評論)。你不能假定你的消息只是因爲沒有更多的字節可以從流中讀取(考慮網絡或I/O爭用)。但是如果你真的想要走這條路,首先調用阻塞'read()',然後調用'available()'一次來查看你可以在沒有阻塞的情況下進一步讀取多少字節。 –

+0

那麼正確的方法是什麼? – marco

1

available()本身不吃CPU。這是什麼是你的循環:

while (buffer.available() > 0) { 
    readCharacter.append((char) buffer.read()); 
} 

雖然字節是不可用的,你實際上是調用available()多次(可能是幾千倍)。由於read()流的方法阻塞,所以根本不需要撥打available()。以下代碼的功能相同,但不會佔用CPU。

String line = null; 
while ((line = buffer.read()) != null) { 
    readCharacter.append(line); 
} 
+0

你的例子因爲InputStream.read()有一個返回類型的'int'而不是'String'。你可能是指'BufferedReader.readLine()'方法。 –

+0

BufferedInputStream沒有readLine()方法.. – marco

+1

當然我的意思是'BufferedReader'。可能是變量名''buffer'讓我困惑。無論如何,這不是問題。應該使用'available()'的時間和地點的問題。 – AlexR