一、场景
-
假设容器中只能存放一件物品,生产者将生产出的产品放入容器,消费者将从容器产品取走消费 -
如果容器中没有产品,则生产者将产品放入容器,,否则停止生产并等待,直到容器中的产品被消费者取走为止 -
如果容器中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到容器中再次放入产品为止
这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间互相依赖互为条件
二、解决方法
1.管程法
生产者将生产好的数据放入缓冲区,消费者从缓冲区中拿出数据
生产者:负责生产数据的模块(可能是对象、方法、线程、进程)
消费者:负责处理数据的模块(可能是对象、方法、线程、进程)
缓冲区:消费者不能之间使用生产者生产的数据,需要通过缓冲区处理
2.信号灯法
????????来判断一个标志位flag,如果为true,就让他等待、如果为false,就让他去通知另外一个人、把两人衔接起来,就像咱们的信号灯红灯停,绿灯行,通过这样一个判断方式,只要来判断什么瑞后让他等待,什么时候将他唤醒就ok
三、代码实现
1.管程法
产品类
public class Product{
//产品编号
public int id;
public Product(int id) {
this.id = id;
}
}
缓冲区
public class Buffer {
//容器大小
Product[] products = new Product[10];
//计数器,用来判断容器容量
int count;
//生产者放入产品
public synchronized void push(Product product) throws InterruptedException {
//如果容器满了,需要等待消费者消费
if (count == products.length){
//通知消费者消费,通知生产者等待
this.wait();
}
//如果容器没有满,生产者需要将产品放入容器
products[count] = product;
count++;
//可以通知消费者进行消费了
this.notifyAll();
}
//消费者消费产品
public synchronized Product pop() throws InterruptedException {
//判断能否消费
if (count == 0){
//等待生产者生产,消费者等待
this.wait();
}
//如果可以消费
count--;
Product product = products[count];
//产品消费完,通知生产者生产
this.notifyAll();
return product;
}
}
生产者类
public class Producer extends Thread{
//缓冲区对象
Buffer container;
public Producer(Buffer container) {
this.container = container;
}
//生产产品
@SneakyThrows
public void run(){
for (int i = 1; i < 100; i++) {
container.push(new Product(i));
System.out.println("生产了第"+i+"个产品");
}
}
}
消费者类
public class Consumer extends Thread {
//缓冲区对象
Buffer container;
public Consumer(Buffer container) {
this.container = container;
}
//消费产品
@SneakyThrows
public void run(){
for (int i = 1; i < 100; i++) {
System.out.println("----->消费了第"+container.pop().id+"个产品");
}
}
}
测试类
public class TestPC {
public static void main(String[] args) {
//缓冲区对象
Buffer buffer = new Buffer();
//生产者对象
new Producer(buffer).start();
//消费者对象
new Consumer(buffer).start();
}
}
2.信号灯法
//测试类
public class TestPC2 {
public static void main(String[] args) {
Product2 product2 = new Product2();
new Produser2(product2).start();
new Consumer2(product2).start();
}
}
//生产者
class Produser2 extends Thread{
Product2 product2;
public Produser2(Product2 product2) {
this.product2 = product2;
}
@SneakyThrows
public void run(){
for (int i = 0; i < 20; i++) {
if (i % 2 == 0){
this.product2.input("面包");
}else {
this.product2.input("酸奶");
}
}
}
}
//消费者
class Consumer2 extends Thread{
Product2 product2;
public Consumer2(Product2 product2) {
this.product2 = product2;
}
@SneakyThrows
public void run(){
for (int i = 0; i < 20; i++) {
this.product2.output();
}
}
}
//产品
class Product2{
String food;
//消费者等待 T ;生产者等待 F
boolean flag = true;
//生产
public synchronized void input(String color) throws InterruptedException {
if (!flag){
this.wait();
}
System.out.println("生产者生产"+color);
//通知消费者消费
this.notifyAll();
this.food = color;
this.flag = !this.flag;
}
//消费
public synchronized void output() throws InterruptedException {
if (flag){
this.wait();
}
System.out.println("消费者消费了"+ food);
//通知生产者生产
this.notifyAll();
this.flag = !this.flag;
}
}
|