生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法[1]等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。
package XianCheng;
public class Shengchanzhe extends Thread{
public Xiaofeizhe s;
@Override
public void run() {
Lingjieziyuan l=Lingjieziyuan.getInstance();
for (int i = 0; ; i++) {
System.out.print("生产者:"+l.list.size()+" ");
if (l.list.size()!=5) {
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
l.list.add(i); System.out.print(" 生产 ");
System.out.print("消费者的状态:"+s.getState()+" ");
if ((l.list.size()==2 ||l.list.size()==5)&& s.getState()== State.WAITING){
System.out.print(l.list.size());
synchronized (s){
s.notify();
}
}
} else if (l.list.size()==5) {
try {
synchronized (this){
wait();}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println();
}
}
}
package XianCheng;
public class Xiaofeizhe extends Thread{
public Shengchanzhe sc;
@Override
public void run() {
Lingjieziyuan l=Lingjieziyuan.getInstance();
while (true){
System.out.print("消费者:"+l.list.size()+" ");
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (l.list.size()==0){
try {
synchronized (this){
wait();}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else if (l.list.size()!=0) {
System.out.print(" 消费 ");
l.list.remove(0);
System.out.print("生产者的状态:"+sc.getState());
if ((l.list.size()==2 ||l.list.size()==0)&& sc.getState()== State.WAITING){
synchronized (sc){
sc.notify();
}
}
// System.out.print("生产"+sc.getState());
}
System.out.println();
}
}
}
package XianCheng;
import java.util.ArrayList;
import java.util.List;
public class Lingjieziyuan {
List list=new ArrayList<>();
private static Lingjieziyuan instance=new Lingjieziyuan(); // 存储唯一实例的类变量
private Lingjieziyuan() {} // 私有构造方法
public static Lingjieziyuan getInstance() {
// 静态方法,用于获取唯一实例
return instance;
}
}