我从here获得了示例。但他们只是逐个实施这个例子。平均第一个产生的整数然后混淆并编程停止。
以下是原始示例:
class ProducerConsumerImpl {
// producer consumer problem data
private static final int CAPACITY = 10;
private final Queue queue = new LinkedList<>();
private final Random theRandom = new Random();
// lock and condition variables
private final Lock aLock = new ReentrantLock();
private final Condition bufferNotFull = aLock.newCondition();
private final Condition bufferNotEmpty = aLock.newCondition();
public void put() throws InterruptedException {
aLock.lock();
try {
while (queue.size() == CAPACITY) {
System.out.println(Thread.currentThread().getName()
+ " : Buffer is full, waiting");
bufferNotEmpty.await();
}
int number = theRandom.nextInt();
boolean isAdded = queue.offer(number);
if (isAdded) {
System.out.printf("%s added %d into queue %n", Thread
.currentThread().getName(), number);
// signal consumer thread that, buffer has element now
System.out.println(Thread.currentThread().getName()
+ " : Signalling that buffer is no more empty now");
bufferNotFull.signalAll();
}
} finally {
aLock.unlock();
}
}
public void get() throws InterruptedException {
aLock.lock();
try {
while (queue.size() == 0) {
System.out.println(Thread.currentThread().getName()
+ " : Buffer is empty, waiting");
bufferNotFull.await();
}
Integer value = queue.poll();
if (value != null) {
System.out.printf("%s consumed %d from queue %n", Thread
.currentThread().getName(), value);
// signal producer thread that, buffer may be empty now
System.out.println(Thread.currentThread().getName()
+ " : Signalling that buffer may be empty now");
bufferNotEmpty.signalAll();
}
} finally {
aLock.unlock();
}
}
}
之后我修改代码并使其工作,如, 前10个生成,然后10个消耗,循环运行直到程序终止。 这是我修改过的代码:
class ProducerConsumerImpl {
// producer consumer problem data
private static final int CAPACITY = 10;
private final Queue<Integer> queue = new LinkedList<>();
private final Random theRandom = new Random();
// lock and condition variables
private final Lock aLock = new ReentrantLock();
private final Condition bufferNotFull = aLock.newCondition();
private final Condition bufferNotEmpty = aLock.newCondition();
public void put() throws InterruptedException {
aLock.lock();
try {
while(true){
while (queue.size() == CAPACITY) {
System.out.println(Thread.currentThread().getName()
+ " : Buffer is full, waiting");
bufferNotEmpty.await();
}
int number = theRandom.nextInt();
boolean isAdded = queue.offer(number);
if (isAdded) {
System.out.printf("%s added %d into queue %n", Thread
.currentThread().getName(), number);
}
bufferNotFull.signalAll();
}
} finally {
aLock.unlock();
}
}
public void get() throws InterruptedException {
aLock.lock();
try {
while(true){
while (queue.size() == 0) {
System.out.println(Thread.currentThread().getName()
+ " : Buffer is empty, waiting");
bufferNotFull.await();
}
Integer value = (Integer)queue.poll();
if (value != null) {
System.out.printf("%s consumed %d from queue %n", Thread
.currentThread().getName(), value);
}
bufferNotEmpty.signalAll();
}
} finally {
aLock.unlock();
}
}
}
修改它的工作正常后,产生10个随机整数,然后一次又一次地消耗这些整数,直到程序存在/终止。但由于我不是并发的主人/专家。
所以我想问一下我的修改过的代码有什么问题吗?
我在bufferNotFull.signalAll();
和bufferNotEmpty.signalAll();
展示位置感到有问题,因为每次都可以通知等待线程。
如果有问题那我怎么解决?或者如果一切正常,那么请清除bufferNotFull.signalAll(); and bufferNotEmpty.signalAll(); placement, because that could notify waiting thread each time.
混乱。
注意:这只是获取和设置代码。(生产和消费)
修改代码的输出:
PRODUCER added 1062016967 into queue
PRODUCER added 1204607478 into queue
PRODUCER added 1865840177 into queue
PRODUCER added -1279321362 into queue
PRODUCER added -190570442 into queue
PRODUCER added -1344361101 into queue
PRODUCER added 609239106 into queue
PRODUCER added -1480451794 into queue
PRODUCER added 1905208395 into queue
PRODUCER added -420578734 into queue
PRODUCER : Buffer is full, waiting
CONSUMER consumed 1062016967 from queue
CONSUMER consumed 1204607478 from queue
CONSUMER consumed 1865840177 from queue
CONSUMER consumed -1279321362 from queue
CONSUMER consumed -190570442 from queue
CONSUMER consumed -1344361101 from queue
CONSUMER consumed 609239106 from queue
CONSUMER consumed -1480451794 from queue
CONSUMER consumed 1905208395 from queue
CONSUMER consumed -420578734 from queue
CONSUMER : Buffer is empty, waiting
PRODUCER added 1917580670 into queue
so on.........
被修改
在考虑了性能后,我决定在put
语句之前添加if get
和signalall();
方法中的条件。 (我认为它可以提高性能甚至0.000000Something)但是中断await();可能是deadlock();
任何帮助?
对于制片人:
if(queue.size() == CAPACITY){
bufferNotFull.signalAll();
}
对于消费者:
if(queue.size() == 0){
bufferNotEmpty.signalAll();
}
答案 0 :(得分:1)
修改后的代码没问题。
关于在不需要时调用.singnalAll()
调用可能的性能优化:仅当条件从false
更改为true
>时,发出信号就足够了强>
对于制作人,您可以使用:
if(isAdded && queue.size() == 1) {
/*
* Element has been *actually added* *into empty queue*
* (previously .size() = 0), thus *queue become non-empty*.
*/
bufferNotFull.signalAll();
}
对于消费者,您可以使用:
if(value && queue.size() == CAPACITY - 1) {
/*
* Element has been *actually consumed* *from full queue*
* (previousely .size() = CAPACITY), thus *queue become non full*.
*/
bufferNotEmpty.signalAll();
}
注意,这样你就不会消除对服务员不必要的通知(例如,消费者只能等待空队列的元素,因此只添加第一个元素就会唤醒它)。相反,当明确知道没有线程等待它时(例如,消费者不能在非空队列中等待),您将消除对.notifyAll()
的调用。