多线程_23_并发协作_管程法_信号灯法

并发协作模型生产者消费者模式的第一种管程法,它的核心要点是加了缓冲区,有了缓冲区之后,生产者和消费者之间解耦了,比如超市的中间商,生产者向中间商发商品,超市向中间商进商品,而生产者并不知道商品买给谁了。
分析这个模型有几个角色:
第一个角色生产者,第二个角色消费者,它们两个是多线程,第三个是并发容器也就是缓冲区,第四个数据,比如汉堡。生产者往里面填数据,消费者往外面拿数据,所以缓冲区的并发操作存或取。当缓冲区里面的数据是满的,生产者就等待,
当缓冲区没满就生产。当缓冲区里面有数据的时候,消费者就可以消费了,当缓冲区里面为空的时候就等待。
多线程_23_并发协作_管程法_信号灯法_第1张图片
object类提供的wait表示线程等待,notifyAll唤醒第一个处于等待的线程,ontifyAll表示唤醒所有线程
多线程_23_并发协作_管程法_信号灯法_第2张图片
多线程_23_并发协作_管程法_信号灯法_第3张图片
多线程_23_并发协作_管程法_信号灯法_第4张图片
看案例

package com.cb.thread.day05;
/*
 * 协作模型:生产者消费者实现一;管程法
 */

public class CoTest01 {
	public static void main(String[] args) {
		SynConsumer container = new SynConsumer();
		new Producor(container).start();
		new Consumer(container).start();
	}
}

//生产者
class Producor extends Thread{
	SynConsumer consumer ;
	@Override
	public void run() {
		//生产
		for (int i = 0; i < 100; i++) {
			System.out.println("生产-->"+i+"鸡腿汉堡");
			consumer.push(new ChickenHamburger(i));
		}
	}
	public Producor(SynConsumer consumer) {
		this.consumer = consumer;
	}
	
}
//消费者
class Consumer extends Thread{
	SynConsumer consumer ;
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println("消费-->"+consumer.pop().id+"鸡腿汉堡");
			
		}
	}
	public Consumer(SynConsumer consumer) {
		this.consumer = consumer;
	}
}
//缓冲区
class SynConsumer{
	ChickenHamburger[] hamburgers = new ChickenHamburger[10];
	int count = 0;//计数器
	//存储 生产
	public synchronized void  push(ChickenHamburger hamburger){
		//何时可以生产  容器存在空间
		// 不能生产 当容器满了线程阻塞
		if(count == hamburgers.length){
			try {
				this.wait(); // 线程阻塞  消费者通知生产者解除阻塞
			} catch (InterruptedException e) {
			}
		}
		//存在空间 可以生产
		hamburgers[count] = hamburger;
		count++;
		//存在数据了,可以通知消费者消费了
		this.notifyAll();
	}
	//获取
	public synchronized ChickenHamburger pop(){
		//何时消费 容器中是否存 数据
		//没有数据 只能等待
		 if(count==0){
			 try {
				this.wait();//线程阻塞  生产者通知消费解除阻塞
			} catch (InterruptedException e) {
			}
		 }
		//存在数据可以消费
		count--;
		ChickenHamburger hanHamburger = hamburgers[count];
		this.notifyAll();//存在空间了,可以唤醒生产者生产了
		return hanHamburger;
	}
}

//数据:鸡腿堡
class ChickenHamburger{
	int id;

	public ChickenHamburger(int id) {
		this.id = id;
	};
	
}

运行结果:注释写的很清楚,何时生产,当容器有空间了,就可以生产,
当容器满了,生产者等待。何时消费,当容器有数据了就可以消费,当容器没有数据就等待。还有就是当生产者往容器生产数据时,就通知消费者消费,也就是唤醒线程;当消费者处理数据,就唤醒生产者生产者消生产数据。
多线程_23_并发协作_管程法_信号灯法_第5张图片
接下来第二种生产者消费者模式------->信号灯法
多线程_23_并发协作_管程法_信号灯法_第6张图片
接下来模拟我们看电视,演员演什么,观众看什么,当演员演戏的时候,观众等待,当我们看的时候,演员等待。

package com.cb.thread.day05;
/*
 * 协作模型:生产者消费者实现二; 信号灯法
 * 借助标志位
 */

public class CoTest02 {
	public static void main(String[] args) {
		Tv tv = new Tv();
		new Player(tv).start();
		new Watcher(tv).start();
	}
}
//生产者 演员
class Player extends Thread{
	Tv tv;
	
	public Player(Tv tv) {
		this.tv = tv;
	}

	public void run() {
		for (int i = 0; i < 20; i++) {
			if(i%2==0){
				this.tv.paly("男篮世界杯");
			}else {
				this.tv.paly("周琦连线球失误");
			}
		}
	}
}
//消费者 观众
class Watcher extends Thread{
	Tv tv;
	
	public Watcher(Tv tv) {
		this.tv = tv;
	}

	public void run() {
		for (int i = 0; i < 20; i++) {
			this.tv.watch();
		}
		
	}
}
//同一个资源 电视
class Tv{
	String voice;
	
	//信号灯
	//真 表示演员表演 观众等待
	//假 表示观众观看 演员等待
	boolean flag = true;
	
	//表演
	public synchronized void paly(String voice){
		//演员等待
		if(!flag){
			try {
				this.wait();
			} catch (InterruptedException e) {
			}
		}
		//表演时刻
		System.out.println("表演了:"+voice);
		this.voice = voice;
		//表演结束,唤醒观众
		 this.notify();
		 //切换标志
		 this.flag=!this.flag;
		
	}
	//观看
	public synchronized void watch(){
		//观众等待
		if(flag){
			try {
				this.wait();
			} catch (InterruptedException e) {
			}
		}
		//观看
		System.out.println("听到了:"+ voice);
		//观看结束,唤醒演员
		 this.notify();
		 //切换标志
		 this.flag= !this.flag;
	}
}
	

运行结果:
多线程_23_并发协作_管程法_信号灯法_第7张图片

你可能感兴趣的:(多线程)