我无法理解为什么消费者线程仅在生产者写完 10 个对象后才执行。如果我根据 javadoc 看到只有同步块(synchronized block)完成时才会执行线程,我认为在下面的情况下该 block 不会完成,因为执行在同步块(synchronized block)内循环进行。
根据java文档通知方法注释
The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.
Runnable consumer = (() -> {
synchronized (BUFFER) {
while(true) {
try {
while(BUFFER.isEmpty()) {
BUFFER.wait();
}
System.out.println("consuming "+BUFFER.poll());
System.out.println("size "+BUFFER.size());
TimeUnit.SECONDS.sleep(1);
BUFFER.notify();
} catch (InterruptedException e) {
}
}
}});
Runnable producer = (() -> {
synchronized (BUFFER) {
while(true) {
try {
while(BUFFER.size() == 10) {
BUFFER.wait();
}
Random random = new Random();
System.out.println("producing "+BUFFER.offer(random.nextInt()));
TimeUnit.SECONDS.sleep(1);
BUFFER.notify();
} catch (Exception e) {
}
}
}
});
executor.submit(consumer);
executor.submit(producer);
OUTPUT
producing true
producing true
producing true
producing true
producing true
producing true
producing true
producing true
producing true
producing true
consuming 1494680650
size 9
consuming 2055368049
size 8
[comment]: SUCCESS: Assembly.Load(ProcMonInject, Version=2.7.5159.0, Culture=neutral, PublicKeyToken=d34a061f079be347)
consuming 569414348
size 7
consuming -1146378118
size 6
consuming -2025680888
size 5
consuming -1624438827
size 4
consuming -2035450589
size 3
consuming 953341046
size 2
consuming 776364558
size 1
consuming -2019340509
size 0
producing true
最佳答案
当您从生产者线程调用 BUFFER.notify() 时,消费者线程将被唤醒并尝试获取 Buffer 对象上的锁。但生产者线程仍然拥有缓冲区对象的锁(因此消费者必须等待它被释放)。当生产者满足条件 while(BUFFER.size() == 10)
时,它将释放缓冲区对象上的锁。
这次消费者将获取锁并消耗缓冲区。直到满足条件while(BUFFER.isEmpty())
并释放锁。
仅供引用;生产者-消费者可以在不使用锁的情况下编写,使用 LinkedBlockingQueue类(class)。 (如果你给队列一个容量,当容量满时,生产者线程将被阻塞。当队列中没有项目时,消费者线程将被阻塞。)
关于java - 为什么消费者线程只有在生产者写完10个对象后才执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55401524/