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

Java 将一组对象从一个线程传递到另一个线程的最快数据存储是什么?,java,performance,storage,Java,Performance,Storage,我有两个线程,一个读取流并从其内容生成数据对象 然后我必须将它们传递到第二个线程,将它们写入数据库 我想将这两个任务分开(这就是为什么我使用两个线程),因为流和数据库的I/O性能不同。在某些情况下,流速度很快,有时,db会有一些延迟 所以我想在它们之间放置一些(非常简单的!)数据存储 我的第一个想法是一个FILO解决方案,必须是线程安全的,并且应该是快速的(没有花哨的东西,只是放和拉)。顺序无关紧要。在某些时候,存储器中可能会有大约100000个条目(在使用db进行大约1秒的ping之后就是这种

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

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

我想将这两个任务分开(这就是为什么我使用两个线程),因为流和数据库的I/O性能不同。在某些情况下,流速度很快,有时,db会有一些延迟

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

我的第一个想法是一个FILO解决方案,必须是线程安全的,并且应该是快速的(没有花哨的东西,只是放和拉)。顺序无关紧要。在某些时候,存储器中可能会有大约100000个条目(在使用db进行大约1秒的ping之后就是这种情况)


每个对象都有一个小的足迹,这正是生产者-消费者模式。看一看它的设计和实现

以下是我的示例代码:

公共类生成器实现可运行{
私有阻塞队列;
公共生产者(封锁队列){
this.queue=队列;
}
@凌驾
公开募捐{
//生产1000种产品
对于(int i=0;i<1000;i++){
queue.put(新产品());
System.out.println(“生产产品”);
}
}
}
公共类使用者实现可运行{
私有阻塞队列;
公共消费者(封锁队列){
this.queue=队列;
}
@凌驾
公开募捐{
while(true){
Product=queue.take();
系统输出打印项次(“消费品”);
}
}
}
这是呼叫代码:
BlockingQueue=new ArrayBlockingQueue(50);
生产者=新生产者(队列);
新线程(producer.start();
消费者=新消费者(队列);
新线程(consumer.start();

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

在大于操作系统内存页大小的线程之间批量传递对象

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

如果不这样做,那么内存页在内核之间来回乒乓

如果你复制,那么它是相同的。当writer线程写入一个页面,而reader线程读取同一页面时,CPU将花费时间确保两个内核看到相同的数据

所以我会让读者读一堆东西,比如说价值16k的东西,而不是提供给消费者线程。填充完这些页面后,将它们释放到处理器线程,并分配另一个16k数据块以开始填充更多对象

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