与管程法相比,信号灯法判断生产者(消费者)是否能能够放入(取出)产品的依据是标志位。
管程法则是通过容器是否有产品和是否超过容器容量等变量来判断。
打个比方,现在有一张桌子D,一个放苹果的人A(生产者),一个吃苹果的人B(消费者),以及苹果C。桌子可以放一个苹果。现在有个标志flag,当标志为true的时候,B才可以去吃,吃了后,标志位变为false,通知A再去放,如果B没有吃,A就一直等待。
以下是用java模拟的信号灯法的代码
import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
* @ProductName:
* @ProjectName:
* @Package:
* @Description: 生产者消费者 -信号灯法
* @Author: 四叶总会来的
* @Date: 2021/10/11 13:57
* @UpdateRemark:
* @Version: 1.0
* <p>
*/
@Slf4j
public class ProduceAndConsumer1 {
public static void main(String[] args) {
Desk desk = new Desk(new Fruit("苹果"));
Consumer1 consumer1 = new Consumer1(desk);
Productor1 productor1 = new Productor1(desk);
consumer1.start();
productor1.start();
}
}
/**
* 生产者
*/
class Productor1 extends Thread {
//生产产品
/**
*
*/
Desk desk;
/**
*
*/
public Productor1(Desk desk) {
this.desk = desk;
}
@SneakyThrows
@Override
public void run() {
while (true) {
desk.putDesk(desk.fruit);
}
}
}
/**
* 消费者
*/
class Consumer1 extends Thread {
/**
*
*/
Desk desk;
/**
*
*/
public Consumer1(Desk desk) {
this.desk = desk;
}
@SneakyThrows
@Override
public void run() {
while (true){
desk.getDesk();
}
}
}
/**
* 产品
*/
class Fruit {
/**
*
*/
String name;
public Fruit(String name) {
this.name = name;
}
}
/**
* 容器
*/
@Slf4j
class Desk {
/**
*
*/
private Boolean flag = false;//true代表可以拿,false代表可以放
/**
*
*/
public Fruit fruit;
public Desk(Fruit fruit) {
this.fruit = fruit;
}
public synchronized void putDesk(Fruit fruit) throws InterruptedException {
if (flag == true) {
log.info("已放入,等待中");
this.wait();
}
log.info("我放了一个" + fruit.name);
this.flag = true;
this.notifyAll();
}
public synchronized void getDesk() throws InterruptedException {
if (flag == false) {
log.info("拿不了,等待中");
this.wait();
}
log.info("我从桌子上拿了一个水果");
this.flag = false;
this.notifyAll();
}
}