2012-01-10 34 views
1

我一直在使用this教程來了解使用套接字IO的簡單文件傳輸客戶端/服務器。我將響應處理程序更改爲接受多個讀取作爲一個文件的一部分,因爲我將處理大型文件,可能高達500 MB。本教程沒有考慮到大型服務器響應,所以我掙扎了一下,並且創建了競爭條件。如何在Rox NIO教程中消除競態條件

這裏的響應處理程序代碼:

public class RspHandler { 

private byte[] rsp = null; 
public synchronized boolean handleResponse(byte[] rsp) { 
    this.rsp = rsp; 
    this.notify(); 
    return true; 
} 

public synchronized void waitForResponse() { 
    while(this.rsp == null) { 
     try { 
      this.wait(); 
     } catch (InterruptedException e) { 
     } 
    } 
    System.out.println("Received Response : " + new String(this.rsp)); 
} 

public synchronized void waitForFile(String filename) throws IOException { 
    String filepath = "C:\\a\\received\\" + filename; 
    FileOutputStream fos = new FileOutputStream(filepath); 
    while(waitForFileChunk(fos) != -1){} 
    fos.close(); 
} 

private synchronized int waitForFileChunk(FileOutputStream fos) throws IOException 
{ 
    while(this.rsp == null) { 
     try { 
      this.wait(); 
     } catch (InterruptedException e) { 
     } 
    } 
    fos.write(this.rsp); 
    int length = this.rsp.length; 
    this.rsp = null; 
    if(length < NioClient.READ_SIZE)//Probably a bad way to find the end of the file 
    { 
     return -1; 
    } 
    else 
    { 
     return length; 
    } 

} 
} 

該方案的主要線程創建主線程上的RspHandler,並把它傳遞到客戶端,在單獨的線程創建的。主線程告訴客戶端請求文件,然後告訴RspHandler監聽響應。當客戶端從服務器讀取(它現在讀取大約1KB的塊)時,它調用handleResponse(byte[] rsp)方法,填充rsp字節數組。

本質上,我不會像接收到的那樣快速地將接收到的數據寫入文件。我對線程有點新,所以我不知道該怎麼做才能擺脫這種競爭條件。任何提示?

回答

3

這是經典的消費者/生產者。處理這個問題的最直接/最簡單的方法是使用BlockingQueue。生產者電話put(),消費者來電take()

注意,使用BlockingQueue通常會導致「我該如何完成」問題。要做到這一點的最好方法是使用「毒丸」方法,即生產者在隊列中粘貼一個「特殊」值,告知消費者沒有更多數據。

+0

對,BlockingQueue爲我解決了,謝謝! – Indigenuity 2012-01-11 20:06:50