将一组对象从一个线程传递到另一个线程的最快数据存储是什么?

时间:2012-06-22 13:48:39

标签: java performance storage

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

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

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

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

我的第一个想法是FILO解决方案,必须是线程安全的并且应该是快速的(没有花哨的东西,只是放置和拉动)。订单无关紧要。在某些时候,存储中可能存在大约100,000个条目(在与db一起大约一秒钟之后就是这种情况)。

每个对象的占用空间都很小,<1kb。

你会向我推荐什么?

2 个答案:

答案 0 :(得分:6)

这正是生产者 - 消费者模式。看看BlockingQueue及其实现。

以下是我blog的示例代码:

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();

答案 1 :(得分:1)

不要在线程之间复制对象。将指针传递给线程之间的对象。并尝试在内存中保持对象顺序。这样,当您在线程之间传递一批对象时,CPU只需在CPU之间重新映射一些内存页。

批量传递大于OS内存页面大小的线程之间的对象。

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

如果你不这样做,那么内存页面就会在核心之间来回打乒乓。

如果你复制,那就是一样的。当写入程序线程写入一个页面,并且读取器线程正在同一页面上读取时,CPU花费时间确保两个核心都看到相同的数据。

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