Java 从BlockingQueue提取时缺少项
我有一个庞大的数据集,我需要将其填充到数据库中。我正在编写一个基于Java并发库(具有BlockingQueue和executorService的生产者-消费者模型)的代码,它可以在队列到达时不断向队列添加数据。消费者一直在检索数据,除非遇到“毒药”(然后它就死了) 主类,带有要发布的虚拟数据。有意将队列大小保持较小:Java 从BlockingQueue提取时缺少项,java,multithreading,concurrency,queue,executorservice,Java,Multithreading,Concurrency,Queue,Executorservice,我有一个庞大的数据集,我需要将其填充到数据库中。我正在编写一个基于Java并发库(具有BlockingQueue和executorService的生产者-消费者模型)的代码,它可以在队列到达时不断向队列添加数据。消费者一直在检索数据,除非遇到“毒药”(然后它就死了) 主类,带有要发布的虚拟数据。有意将队列大小保持较小: public class MessageProcessor { private static final BlockingQueue<String> queue =
public class MessageProcessor {
private static final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(
5, true);
private static final ExecutorService executor = Executors
.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private static final ExecutorService consumerExecutor = Executors
.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private static final String POISON = "THE_END";
public void processMessages() throws InterruptedException {
//Create and start consumer
Runnable consumer = new MessageConsumer(queue);
consumerExecutor.execute(consumer);
for (String payload : getPayload()) {
//create and start producer with given payload
Runnable producer = new MessageProducer(queue, payload);
executor.execute(producer);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
consumerExecutor.shutdown();
consumerExecutor.awaitTermination(1, TimeUnit.MINUTES);
}
private List<String> getPayload() {
List<String> payloads = new ArrayList<>();
payloads.add("data1");
payloads.add("data2");
payloads.add("data3");
payloads.add("data4");
payloads.add("data5");
payloads.add("data6");
payloads.add("data7");
payloads.add("data8");
payloads.add("data9");
payloads.add("data10");
payloads.add(POISON);
return payloads;
}}
执行new MessageProcessor.processMessages()时,我观察到两种异常情况:
谢谢 将条目放入队列是不确定的,因为您对每条消息使用唯一的runnable,而不是在单个线程中顺序循环
正如您所说,这可能解释了为什么有些消息看不见,因为它们可能在结尾之后 将条目放入队列是不确定的,因为您对每条消息使用唯一的runnable,而不是在单个线程中顺序循环
正如您所说,这可能解释了为什么有些消息看不见,因为它们可能在结尾之后 你的两个问题是一样的
由于有多个生产者并行运行,因此不能保证第一个生产者将其元素放在第二个生产者之前的队列中。因此,这些项目在队列中没有按顺序排列,毒药出现在data4之前,因此消费者不会消费data4 你的两个问题是一样的
由于有多个生产者并行运行,因此不能保证第一个生产者将其元素放在第二个生产者之前的队列中。因此,这些项目在队列中没有按顺序排列,毒药出现在data4之前,因此消费者不会消费data4 您的队列是fifo,是的,但您没有按fifo顺序将数据推送到队列中
如果.availableProcessors()返回>1,则有多个生产者将数据推送到队列中-您的执行者管理的线程不能保证按照您调用的顺序顺序运行
executor.execute(生产者)
in.您的队列是fifo,是的,但您没有按fifo顺序将数据推送到队列中
如果.availableProcessors()返回>1,则有多个生产者将数据推送到队列中-您的执行者管理的线程不能保证按照您调用的顺序顺序运行
executor.execute(生产者)
in.是的,对于我的特定场景,我必须在线程的父线程(一个单独的线程)中处理数据-尽管,正如你所说,这解释了上述行为..是的,对于我的特定场景,我必须在线程的父线程(一个单独的线程)中处理数据-尽管,正如你所说,这就解释了上述行为。.感谢-通过从列表中移除毒药并在生产者执行器终止后直接向队列添加毒药来修复此问题。感谢-通过从列表中移除毒药并在生产者执行器终止后直接向队列添加毒药来修复此问题。
public class MessageProducer implements Runnable {
private BlockingQueue<String> queue;
private String payload;
public MessageProducer(BlockingQueue<String> queue, String payload) {
this();
this.queue = queue;
this.payload = payload;
}
private MessageProducer() {
}
public void run() {
try {
queue.put(payload);
System.out.println("Put : " + payload );
} catch (InterruptedException e) {
e.printStackTrace();
}
}}
public class MessageConsumer implements Runnable {
private BlockingQueue<String> queue;
private static final String POISON = "THE_END";
public MessageConsumer(BlockingQueue<String> queue) {
this();
this.queue = queue;
}
private MessageConsumer() {
}
public void run() {
String payload = "";
do {
try {
payload = queue.take();
System.out.println("Got : " + payload );
} catch (InterruptedException ie) {
// handle
break;
}
} while (!payload.equals(POISON));
}}
Put : data1
Put : data2
Put : data3
Put : data7
Put : data6
Put : data5
Got : data1
Got : data2
Got : data3
Got : data5
Put : data10
Put : data8
Put : data9
Got : data6
Got : data7
Put : data4
Put : THE_END
Got : data8
Got : data9
Got : data10
Got : THE_END