1

私は生産者/消費者問題に似たプログラムを書いています。これが私のメインコードです:

public class PipeProcessor {

private volatile boolean close = false;

Pipe pipe;
Output out;

public PipeProcessor(Pipe pipe)
{
    this.pipe = pipe;
}

public void run()
{
    while(!close)
    {
        out.output(pipe.get());
    }

    while(pipe.size() > 0)
        out.output(pipe.get());

    out.close();

}

public void close()
{
    close = true;
}
}

パイプはArrayBlockingQueueのラッパーであり、バッファーとして機能します。Outputは、バッファ内の要素を取得して出力するクラスです。

PipeProcessorが正常に終了することを確認したい。つまり、閉じるように通知されたときに、バッファーをクリーンアップする。close()メソッドはシャットダウンフックによって呼び出されるため、プロセッサが閉じている間はバッファがいっぱいになっていないことを確認しています。これは正しい方法ですか?ありがとうございました。

4

4 に答える 4

1

あなたのコードは、あなたがやりたいことをしているように見えます。ネーミングを見ると、コードを理解しやすくすることができます。たとえば、ブール値の「閉じる」を「閉じる」または「シャットダウンする」という名前にするか、「実行中」に逆にすることで、より読みやすいコードになります。

while ループrun()とそれに続く行は、次のように記述できます。

    while (running || pipe.size() > 0) {

        out.output(pipe.get());
    }
于 2009-12-26T10:20:10.327 に答える
1

out.close() が必ずしも呼び出されるとは限らないのではないかと心配しています。Pipe.get() がArrayBlockingQueue.take () のようにブロックし、クロージャーを検出したときにセンチネル値を返さない場合、パイプが空になった後に PipeProcessor で close() を呼び出しても効果はありません。条件は再度評価されません。

しかし、おそらく (1) パイプは常に最初に閉じられ、(2) Pipe.get() は閉鎖を検出し、(3) Output が処理できる null のようなセンチネル値を返します。この場合、コードは適切に見えます。

于 2009-12-26T17:38:11.603 に答える
0

パイプを閉じるときにパイプをクリーニングしようとしている理由がわからない場合は、パイプを破棄して GC にクリーンアップさせてみませんか? 私が見る限り、必要なのはクローズと最初のループだけです。

于 2009-12-26T10:07:22.777 に答える
0

プロセスが停止する前にパイプライン内のすべての要素を処理したい場合、実際にシャットダウン フックを使用するとは思いません。メイン コードで明示的にパイプラインをシャットダウンし、それが完了するまで待機します。メインスレッドを終了させます。close()パイプラインが完了するまでメソッドをブロックするように変更するか、別のメソッドを追加することをお勧めします(例: waitForPipelineToEmpty())。

このようにして、すべてをより制御しやすくすることができます。特に、システムの他のビットがシャットダウンフックで自分自身をクリーンアップしている間、物事を処理しようとしないことを意味します.

プロデューサ/コンシューマ キューを終了する別の方法の 1 つは、「今すぐ停止」を意味するセンチネル値を設定することです。次に、それをパイプラインの最後にフィードするだけです(そして、これ以上「実際の」値を追加しないようにします)。プロセッサは、そのアイテムを検出すると停止します。

于 2009-12-26T10:23:23.617 に答える