1

これに具体的に対処する方法がわかりません(Javaの新機能)。基本的に、メモリを超えた多くのデータを生成するプログラムがあります (たとえば、10 ギガのデータと 4 ギガの RAM があります)。データを取得してディスクに書き込むスレッドをフォークすることにしましたが、ディスクへの書き込みがそれを生成するプロセスに追いつかないことはわかっていますが、アプリケーションがディスクへの書き込み速度にバインドできることを望んでいました。しかし、しばらくするとヒープ不足のエラーが発生します。

関連すると思われる部分は次のとおりです。書き込まれるすべてのデータは、この変数に入れられます。

private static Queue<short[]> result =  new LinkedList <short[]> ();

ファイルに保存する部分は次のとおりです。

   static class SaveToFile extends Thread {


        public void run() {
                FileWriter bw = null;
                try {
                    bw = new FileWriter("output.csv");
                    Thread.sleep(500); //delay the start so the queue can have some data
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            System.out.println("size of results during execution is " + result.size());
            while(!result.isEmpty()) {
                short[] current = result.poll();
                try {
                    bw.write(Arrays.toString(current) + "," + "\n");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            try {
                bw.flush();
                bw.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("file writing is done");
        }
    }

何が間違っているのかわかりません。結果のキューを特定のサイズでブロックして、プロセスが書き込みを停止する必要がありますか? または、ファイルへの書き込みに何か問題がありますか? バッファリングされていないバージョンを表示していますが、bufferedWriter を試してみましたが、同じ結果が得られましたか? プログラムの実行中にファイル サイズが 0 になっていることを確認しましたが、一度だけクラッシュしたように見えます。

私の考えは、SaveToFile スレッドがキューをクリアすると、他のプロセスがキューに書き込みを続けるためのスペースが増えるということでした (これらは、私が実行している唯一のスレッド、メイン プログラムと SaveToFile です)。

4

2 に答える 2

1

プロセスが結果のキューへの書き込みを停止するように、結果のキューを特定のサイズでブロックする必要がありますか?

そうです。プロデューサーがデータを書き出すよりも速く生成することが、プロセスのメモリ不足の原因である可能性が最も高いです。

もう1つの問題は、同期されていないことです。そのため、を使用してスレッド間でデータを渡す場合はLinkedList、ロックを使用する必要があります。LinkedList

容量を制限するには、ArrayBlockingQueueまたはを使用できますLinkedBlockingQueue。追加のボーナスとして、どちらもスレッドセーフであるため、外部同期は必要ありません。

最後に、コードがI / Oバウンドである場合、見たところ、コードを2つのスレッドに分割しても比較的メリットはほとんどありません。これは覚えておく価値があります。なぜなら、ほとんどまたはまったくメリットがないために、この余分な複雑さをすべて導入している可能性があるからです。

于 2012-05-28T16:29:32.570 に答える
1

すでに述べたように、ディスクライターはメモリーライターよりも低速です。したがって、結果が空になることはないため、フラッシュ部分に到達することはないと思います。

その中にキューを含むクラスを作成し、最大キューサイズを確立するのが最善の方法だと思います。そのため、メモリライターが何かをキューに入れようとすると、ブロックされます。

キュー メソッドはビジー待機を行わず、デキュー メソッドからのシグナルを待機してスリープ状態にすることをお勧めします。

于 2012-05-28T16:35:38.643 に答える