2012-01-10 13 views
1

私は、ソケットIOを使用して単純なファイル転送クライアント/サーバーのためにthisチュートリアルを使用しています。 1つのファイルの一部として複数の読み込みを受け入れるように応答ハンドラを変更しました。大きなファイルを扱うので、最大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を使用すると、通常、「どのように完了するか」という問題が発生します。これを行う最善の方法は、プロデューサーがキューに「特別な」値を貼って消費者にそれ以上のデータがないことを知らせる「poison pill」メソッドを使用することです。

+0

はい、BlockingQueueは私のためにそれを解決しました、ありがとう! – Indigenuity