BlockingQueue и Capacity
Вопрос такой: Почему, если capacity = 5, то при запуске программы, в консоли иногда проскакивают Producer и Consumer чаще, чем по 5 раз подряд?
Пример:
Producer 50
Producer 43
Producer 30
Producer 43
Producer 41
Producer 88
Producer 36
Consumer 50
Consumer 43
Consumer 30
Consumer 43
Почему продюсера 7 шт?
public class ProducerConsumerProblemWIthQueue {
public static final BlockingQueue<Integer> buffer = new ArrayBlockingQueue<>(5);
public static void problemWIthQueue() {
Thread producer = new Thread(() -> {
while (true) {
produce();
}
});
Thread consumer = new Thread(() -> {
while (true) {
consumer();
}
});
producer.start();
consumer.start();
}
private static void produce() {
int randomInt = ThreadLocalRandom.current().nextInt(100);
System.out.println("Producer " + randomInt);
try {
buffer.put(randomInt);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private static void consumer() {
Integer take;
try {
take = buffer.take();
System.out.println("Consumer " + take);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Ответы (1 шт):
Основная проблема представленного кода в том, что метод produce печатает значения до вызова блокирующего метода put.
Если организовать вывод после вызова блокирующего метода и показывать содержимое очереди:
private static void produce() {
int randomInt = ThreadLocalRandom.current().nextInt(100);
try {
buffer.put(randomInt);
System.out.println("Producer: " + randomInt + " -> " + buffer);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
можно увидеть следующую картину:
Consumer: 9 -> []
Producer: 9 -> [9]
Producer: 5 -> [5]
Consumer: 5 -> []
Producer: 83 -> [83]
Consumer: 83 -> []
Producer: 56 -> [56]
Consumer: 56 -> []
Producer: 44 -> [44]
Consumer: 44 -> []
Producer: 72 -> [72]
Consumer: 72 -> []
Producer: 27 -> [27]
Consumer: 27 -> []
Consumer: 21 -> []
Producer: 21 -> [21]
Consumer: 5 -> []
Producer: 5 -> [5]
Producer: 3 -> [3]
Consumer: 3 -> []
то есть, вывод будет несинхронизирован относительно изменений в самой очереди: сообщение из потока consumer попадает в поток вывода раньше, чем из потока producer, и аналогично в выводе может появиться 6 и более сообщений из потока producer, но при этом в самой очереди не будет более 5 элементов:
Producer: 73 -> [73]
Producer: 13 -> [13]
Producer: 32 -> [13, 32]
Producer: 77 -> [13, 32, 77]
Producer: 56 -> [13, 32, 77, 56]
Producer: 77 -> [13, 32, 77, 56, 77]
Consumer: 73 -> []
Consumer: 13 -> [32, 77, 56, 77]
Producer: 82 -> [32, 77, 56, 77, 82]
Consumer: 32 -> [77, 56, 77, 82]
Producer: 30 -> [77, 56, 77, 82, 30]
Consumer: 77 -> [56, 77, 82, 30]
Producer: 86 -> [56, 77, 82, 30, 86]
Consumer: 56 -> [77, 82, 30, 86]