Java 如何避免多生产者和消费者的饥饿? 这里考虑两个生产者线程和一个消费者线程 假设队列已满 两个生产者线程进入等待状态,因为队列已满 消费者线程从队列中获取元素并通知所有人,所以一个生产者线程添加元素并退出,另一个生产者线程保持等待状态,另一个生产者线程再次添加元素并退出 所以,如果您观察到有一个线程可能总是处于等待状态
如何避免这种情况Java 如何避免多生产者和消费者的饥饿? 这里考虑两个生产者线程和一个消费者线程 假设队列已满 两个生产者线程进入等待状态,因为队列已满 消费者线程从队列中获取元素并通知所有人,所以一个生产者线程添加元素并退出,另一个生产者线程保持等待状态,另一个生产者线程再次添加元素并退出 所以,如果您观察到有一个线程可能总是处于等待状态,java,multithreading,producer-consumer,blockingqueue,Java,Multithreading,Producer Consumer,Blockingqueue,如何避免这种情况 import java.util.LinkedList; import java.util.List; interface BlockingQueueCustom<E> { void put(E item) throws InterruptedException ; E take() throws InterruptedException; } class LinkedBlockingQueueCustom<E> im
import java.util.LinkedList;
import java.util.List;
interface BlockingQueueCustom<E> {
void put(E item) throws InterruptedException ;
E take() throws InterruptedException;
}
class LinkedBlockingQueueCustom<E> implements BlockingQueueCustom<E> {
private List<E> queue;
private int maxSize; // maximum number of elements queue can hold at a time.
public LinkedBlockingQueueCustom(int maxSize) {
this.maxSize = maxSize;
queue = new LinkedList<E>();
}
public synchronized void put(E item) throws InterruptedException {
while(queue.size() == maxSize) {
this.wait();
}
queue.add(item);
this.notifyAll();
}
public synchronized E take() throws InterruptedException {
while(queue.size() == 0) {
this.wait();
}
this.notifyAll();
return queue.remove(0);
}
}
public class BlockingQueueCustomTest {
public static void main(String[] args) throws InterruptedException {
BlockingQueueCustom<Integer> b = new LinkedBlockingQueueCustom<Integer>(10);
System.out.println("put(11)");
b.put(11);
System.out.println("put(12)");
b.put(12);
System.out.println("take() > " + b.take());
System.out.println("take() > " + b.take());
}
}
import java.util.LinkedList;
导入java.util.List;
接口阻塞队列自定义{
无效放置(E项)抛出中断异常;
E take()抛出中断异常;
}
类LinkedBlockingQueueCustom实现BlockingQueueCustom{
私有列表队列;
private int maxSize;//队列一次可以容纳的最大元素数。
公共LinkedBlockingQueueCustom(int maxSize){
this.maxSize=maxSize;
队列=新的LinkedList();
}
公共同步的void put(E项)抛出InterruptedException{
while(queue.size()==maxSize){
这个。等等();
}
添加(项目);
this.notifyAll();
}
public synchronized E take()引发InterruptedException{
while(queue.size()==0){
这个。等等();
}
this.notifyAll();
返回队列。删除(0);
}
}
公共类阻止QueueCustomTest{
公共静态void main(字符串[]args)引发InterruptedException{
BlockingQueueCustom b=新的LinkedBlockingQueueCustom(10);
System.out.println(“put(11)”);
b、 put(11);
系统输出println(“输出(12)”;
b、 put(12);
System.out.println(“take()>”+b.take());
System.out.println(“take()>”+b.take());
}
}
等待和通知的使用已经过时,因为它的功能有限
对于您的具体问题,我真的建议重构您的解决方案以使用。您将看到可以设置公平性参数。此参数将确保以FIFO方式进行分配,以便一旦您的一个线程获得许可证并将数据放入队列中,当再次阻塞时,它将被带到行的末尾(因此,第二个线程将获得优先级)
希望这有帮助。有几种选择。一种是使用标准的
ArrayBlockingQueue
调用两个参数构造函数。在这种情况下,队列将按照FIFO顺序处理线程,生产者将按照他们尝试将元素放入队列的相同顺序在队列中添加元素
/**
* Creates an {@code ArrayBlockingQueue} with the given (fixed)
* capacity and the specified access policy.
*
* @param capacity the capacity of this queue
* @param fair if {@code true} then queue accesses for threads blocked
* on insertion or removal, are processed in FIFO order;
* if {@code false} the access order is unspecified.
* @throws IllegalArgumentException if {@code capacity < 1}
*/
public ArrayBlockingQueue(int capacity, boolean fair) {...}
这是一个如何将
synchronized
块转换为带有ReentrantReadWriteLock
的代码的示例:将一些小的随机数添加到等待时间中,则有50%的机会让另一个生产者先醒来。或者让缓冲区在每个人都有空间添加内容之前不通知生产者。我们可以简单地保持私有final Lock aLock=new ReentrantLock(true);它可以解决饥饿问题吗?是的,但别忘了在finally
块中调用unlock()
。与锁对象的同步
块不同,退出由锁对象保护的代码块时,默认情况下不会释放锁。
/**
* Creates a new {@code ReentrantReadWriteLock} with
* the given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantReadWriteLock(boolean fair) {...}