多线程并行 之 如何处理同一资源 之 管程法
/**
* @author cj
* @create 2021-12-24 4:28 下午
*/
public class TsetPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
Productor productor = new Productor(synContainer,"a");
Consumer consumer = new Consumer(synContainer);
productor.start();
consumer.start();
}
}
//生产者
class Productor extends Thread{
//生产者生产鸡放入缓冲区,
SynContainer synContainer;
public Productor(SynContainer synContainer,String a){
super(a);
this.synContainer = synContainer;
}
@Override
public void run() {
//生产鸡
for (int i = 0; i < 100; i++) {
synContainer.push(new Chicken(i));
System.out.println(this.getName()+"生产了第:"+i+"只鸡");
}
}
}
//消费者
class Consumer extends Thread{
//消费者从缓存区里吃鸡
SynContainer synContainer;
public Consumer(SynContainer synContainer){
this.synContainer = synContainer;
}
@Override
public void run() {
//吃鸡
for (int i = 0; i < 100; i++) {
Chicken chicken = synContainer.pop();
System.out.println(this.getName()+"吃了第"+chicken.id+"只鸡");
}
}
}
//产品
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer {
//容器
Chicken[] cs = new Chicken[10];
int count = 0;
//放入,鸡在外面,往里放,所以要传参数不要返回值
public synchronized void push(Chicken chicken) {
//判断是否有鸡
if (count == cs.length) {
// 鸡满了,则线程停住,等待消费者吃鸡后的通知
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//到这就是鸡不满了,那就可以生产鸡了
//鸡从生产者那里来的,所以送外面传进来
cs[count] = chicken;
//生产一只加一只,需要后加,第一只才有东西
count++;
//通知消费者,生产好了
this.notifyAll();
}
//取出,鸡在里面,要从里面取,所以不用参数要返回值
public synchronized Chicken pop() {
//先判断是否有鸡吃
if (count == 0) {
//没有鸡吃的时候,就线程停住,等待生产者生产鸡后通知到了再往下走
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//能走到这,意思就是有鸡吃了,准备吃鸡
//让大家知道吃的哪只,不用知道的话可以不要
count--; // 需要先减,因为能到这的count至少都是1,最大是10,如果是1,则跳过了第一只鸡,如果是10,则底下这行交表越界
Chicken chicken = cs[count];
//吃空它
cs[count] = null;
//通知生产者我吃完了
this.notifyAll();
return chicken;
}
//注:由于生产者和消费者的线程不是同时起步,也不是交叉运行,完全看cpu心情,有可能鸡完了的这段时间,生产者却一只都没生产,所以这些代码就变得有意义了
}