我有两个线程,一个读取流并从其内容生成数据对象。
然后我必须将它们传递给第二个线程,将它们写入数据库。
我想将两个任务分开(这就是我使用两个线程的原因)因为流和数据库上的I / O-Performance有所不同。在某些情况下,流很快,有时,db有一些滞后。
所以我想在它们之间放一些(非常简单的!)数据存储。
我的第一个想法是FILO解决方案,必须是线程安全的并且应该是快速的(没有花哨的东西,只是放置和拉动)。订单无关紧要。在某些时候,存储中可能存在大约100,000个条目(在与db一起大约一秒钟之后就是这种情况)。
每个对象的占用空间都很小,<1kb。
你会向我推荐什么?
答案 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数据块以开始填充更多对象。