3

我有两个线程,一个读取流并从其内容中生成数据对象。

然后我必须将它们传递给第二个线程,将它们写入数据库。

我想将这两个任务分开(这就是我采用两个线程的原因),因为流和数据库上的 I/O 性能各不相同。在某些情况下,流很快,有时,数据库有一些滞后。

所以我想在它们之间放置一些(非常简单!)数据存储。

我的第一个想法是 FILO 解决方案,它必须是线程安全的并且应该是快速的(没有花哨的东西,只需放置和拉动)。顺序无关紧要。有时,存储中可能有大约 100,000 个条目(在与数据库 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 内存页面大小的线程之间批量传递对象。

因此,为了获得理想的性能,您希望生产者使用一组内存页面,而消费者使用另一组页面。CPU 将确保一个内核使用的页面映射到该内核上的本地存储,以及另一个内核上的其他页面。

如果你不这样做,那么内存页面就会在内核之间来回切换。

如果你复制,那么它是一样的。当写入器线程写入一页,而读取器线程在同一页上读取时,CPU 会花时间确保两个内核看到相同的数据。

所以我会让读者阅读一堆价值 16k 的物品,而不是让它们可供消费者线程使用。填满这些页面后,将它们释放到处理器线程,并分配另一个 16k 数据块以开始填充更多对象。

于 2012-06-22T18:57:05.333 回答