并发协作模型生产者消费者模式的第一种管程法,它的核心要点是加了缓冲区,有了缓冲区之后,生产者和消费者之间解耦了,比如超市的中间商,生产者向中间商发商品,超市向中间商进商品,而生产者并不知道商品买给谁了。
分析这个模型有几个角色:
第一个角色生产者,第二个角色消费者,它们两个是多线程,第三个是并发容器也就是缓冲区,第四个数据,比如汉堡。生产者往里面填数据,消费者往外面拿数据,所以缓冲区的并发操作存或取。当缓冲区里面的数据是满的,生产者就等待,
当缓冲区没满就生产。当缓冲区里面有数据的时候,消费者就可以消费了,当缓冲区里面为空的时候就等待。

object类提供的wait表示线程等待,notifyAll唤醒第一个处于等待的线程,ontifyAll表示唤醒所有线程



看案例
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;
};
}
运行结果:注释写的很清楚,何时生产,当容器有空间了,就可以生产,
当容器满了,生产者等待。何时消费,当容器有数据了就可以消费,当容器没有数据就等待。还有就是当生产者往容器生产数据时,就通知消费者消费,也就是唤醒线程;当消费者处理数据,就唤醒生产者生产者消生产数据。

接下来第二种生产者消费者模式------->信号灯法

接下来模拟我们看电视,演员演什么,观众看什么,当演员演戏的时候,观众等待,当我们看的时候,演员等待。
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;
}
}
运行结果:

本文深入探讨了生产者消费者模式的两种实现方法:管程法和信号灯法。通过具体案例,详细解释了如何利用线程间的等待和唤醒机制来解决资源竞争问题,确保生产者和消费者之间的高效协作。
2027

被折叠的 条评论
为什么被折叠?



