3

2 つのスレッドがあり、1 つはストリームを読み取り、そのコンテンツからデータ オブジェクトを生成します。

次に、それらを 2 番目のスレッドに渡して、データベースに書き込む必要があります。

ストリームとデータベースの I/O パフォーマンスが異なるため、2 つのタスクを分離したいと考えています (これが 2 つのスレッドを使用した理由です)。場合によっては、ストリームが高速である場合もあれば、db に多少の遅延がある場合もあります。

そこで、それらの間に (非常に単純な!) データストレージを配置することを考えました。

私の最初のアイデアは FILO ソリューションであり、スレッドセーフである必要があり、高速である必要があります (空想的なものはなく、置いて引くだけです)。順序は関係ありません。ある時点で、ストレージに約 100,000 エントリが存在する可能性があります (これは、db で約 1 秒間 ping を実行した後のケースです)。

各オブジェクトのフットプリントは小さく、1kb 未満です。

あなたは私に何をお勧めしますか?

4

2 に答える 2

6

これはまさに生産者と消費者のパターンです。BlockingQueueとその実装を見てください。

私のブログのサンプルコードは次のとおりです。

public class Producer implements Runnable {
    private BlockingQueue queue;

    public Producer(BlockingQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        //Produce 1000 products
        for (int i = 0; i < 1000; i++) {
            queue.put(new Product());
            System.out.println("PRODUCED PRODUCT");
        }
    }
}
public class Consumer implements Runnable {
    private BlockingQueue queue;

    public Consumer(BlockingQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            Product product = queue.take();
            System.out.println("CONSUMED PRODUCT");
        }
    }
}

And here is the calling code:
BlockingQueue queue = new ArrayBlockingQueue(50);

Producer producer = new Producer(queue);
new Thread(producer).start();

Consumer consumer = new Consumer(queue);
new Thread(consumer).start();
于 2012-06-22T13:51:28.553 に答える
1

スレッド間でオブジェクトをコピーしないでください。スレッド間でオブジェクトへのポインターを渡します。そして、オブジェクトをメモリ内で順番に保つようにしてください。このように、スレッド間でオブジェクトのバッチを渡す場合、CPU は CPU 間でいくつかのメモリ ページを再マップするだけで済みます。

OS メモリ ページ サイズよりも大きいバッチで、スレッド間でオブジェクトを渡します。

したがって、理想的なパフォーマンスを得るには、プロデューサーが 1 つのメモリ ページ セットを使用し、コンシューマーが別のページ セットを使用する必要があります。CPU は、1 つのコアで使用されるページがそのコアのローカル ストレージにマップされ、他のコアの他のページがマップされることを確認します。

これを行わないと、メモリ ページがコア間を行ったり来たりすることになります。

コピーしても同じです。ライター スレッドが 1 つのページに書き込み、リーダー スレッドが同じページを読み取るため、CPU は両方のコアが同じデータを参照できるように時間を費やしています。

したがって、読者に 16k 相当のオブジェクトの束を読み取らせ、それらをコンシューマー スレッドで使用可能にしないようにします。これらのページがいっぱいになったら、それらをプロセッサ スレッドに解放し、さらに 16k のデータ ブロックを割り当てて、より多くのオブジェクトを埋め始めます。

于 2012-06-22T18:57:05.333 に答える