Java多线程07_线程通信之管程法与信号灯法

java 专栏收录该内容
19 篇文章 1 订阅

Java多线程07_线程通信之管程法与信号灯法


线程通信 的应用场景是 消费者/生产者问题:

解决线程通信的方法:

wait()				表示线程一直等待,直到接到通知(会释放锁)
wait(long timeout)	指定线程等待的毫秒数
notify()			唤醒一个处于等待状态的线程
notifyAll()			唤醒同一个对象上的所有处于等待状态的线程

管程法(通过缓冲区):

生产者生产商品并存入缓冲区,消费者从缓冲区中消费商品。
消费者消费产品后通知生产者生产,当缓冲区产品不足时,消费者线程等待
生产者生产产品后通知消费者消费,如果缓冲区已满,生产者线程等待

在这里插入图片描述

public class TestPC {
	
	public static void main(String[] args) {
		
		SynContainer container = new SynContainer();
		new Producer(container).start();
		new Customer(container).start();
	}

}

class Producer extends Thread{
	
	SynContainer container;
	
	public Producer(SynContainer container) {
		this.container = container;
	}
	
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("生产了第"+i+"只鸡");
			container.push(new Chicken(i));
		}
	}
	
}

class Customer extends Thread{
	
	SynContainer container;
	
	public Customer(SynContainer container) {
		this.container = container;
	}
	
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("消费了第"+container.pop().id+"只鸡");
			
		}
	}
}

class Chicken{
	int id;

	public Chicken(int id) {
		super();
		this.id = id;
	}

}

//缓冲区
class SynContainer{
	
	Chicken[] chickens = new Chicken[10];
	
	int count = 0;
	
	public synchronized void push(Chicken chicken) {
		
		//如果缓冲区已满则生产者等待
		if(count==chickens.length) {
			try {
				this.wait();
			}catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		//缓冲区未满则生产,并通知消费者消费
		chickens[count]=chicken;
		count++;
		this.notifyAll();
	}
	
	public synchronized Chicken pop() {
		
		//如果缓冲区为空则消费者等待
		if(count==0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		//缓冲区不为空则消费,并通知生产者生产
		count--;
		Chicken chicken = chickens[count];
		this.notifyAll();
		return chicken;
	}
}
生产了第0只鸡
生产了第1只鸡
消费了第0只鸡
生产了第2只鸡
消费了第1只鸡
生产了第3只鸡
消费了第2只鸡
生产了第4只鸡
消费了第3只鸡
消费了第4只鸡
生产了第5只鸡
生产了第6只鸡
消费了第5只鸡
生产了第7只鸡
消费了第6只鸡
生产了第8只鸡
消费了第7只鸡
生产了第9只鸡
消费了第8只鸡
生产了第10只鸡
消费了第9只鸡
生产了第11只鸡
消费了第10只鸡
生产了第12只鸡
消费了第11只鸡
生产了第13只鸡
消费了第12只鸡
生产了第14只鸡
消费了第13只鸡
生产了第15只鸡
生产了第16只鸡
消费了第14只鸡
消费了第16只鸡
生产了第17只鸡
消费了第15只鸡
生产了第18只鸡
消费了第17只鸡
生产了第19只鸡
消费了第18只鸡
生产了第20只鸡
消费了第19只鸡
生产了第21只鸡
消费了第20只鸡
生产了第22只鸡
消费了第21只鸡
生产了第23只鸡
消费了第22只鸡
生产了第24只鸡
消费了第23只鸡
生产了第25只鸡
消费了第24只鸡
生产了第26只鸡
消费了第25只鸡
生产了第27只鸡
消费了第26只鸡
生产了第28只鸡
消费了第27只鸡
生产了第29只鸡
消费了第28只鸡
生产了第30只鸡
消费了第29只鸡
生产了第31只鸡
消费了第30只鸡
生产了第32只鸡
消费了第31只鸡
生产了第33只鸡
消费了第32只鸡
生产了第34只鸡
消费了第33只鸡
生产了第35只鸡
消费了第34只鸡
生产了第36只鸡
消费了第35只鸡
生产了第37只鸡
消费了第36只鸡
生产了第38只鸡
消费了第37只鸡
生产了第39只鸡
消费了第38只鸡
生产了第40只鸡
消费了第39只鸡
生产了第41只鸡
消费了第40只鸡
生产了第42只鸡
消费了第41只鸡
生产了第43只鸡
消费了第42只鸡
生产了第44只鸡
消费了第43只鸡
生产了第45只鸡
消费了第44只鸡
生产了第46只鸡
消费了第45只鸡
生产了第47只鸡
消费了第46只鸡
生产了第48只鸡
消费了第47只鸡
生产了第49只鸡
生产了第50只鸡
消费了第48只鸡
生产了第51只鸡
消费了第50只鸡
生产了第52只鸡
消费了第51只鸡
生产了第53只鸡
消费了第52只鸡
生产了第54只鸡
消费了第53只鸡
生产了第55只鸡
消费了第54只鸡
生产了第56只鸡
消费了第55只鸡
生产了第57只鸡
消费了第56只鸡
生产了第58只鸡
消费了第57只鸡
消费了第58只鸡
生产了第59只鸡
消费了第49只鸡
生产了第60只鸡
消费了第59只鸡
生产了第61只鸡
消费了第60只鸡
生产了第62只鸡
消费了第61只鸡
生产了第63只鸡
消费了第62只鸡
生产了第64只鸡
消费了第63只鸡
生产了第65只鸡
消费了第64只鸡
生产了第66只鸡
消费了第65只鸡
生产了第67只鸡
消费了第66只鸡
生产了第68只鸡
消费了第67只鸡
生产了第69只鸡
消费了第68只鸡
生产了第70只鸡
消费了第69只鸡
生产了第71只鸡
消费了第70只鸡
生产了第72只鸡
消费了第71只鸡
生产了第73只鸡
消费了第72只鸡
生产了第74只鸡
消费了第73只鸡
生产了第75只鸡
消费了第74只鸡
生产了第76只鸡
消费了第75只鸡
生产了第77只鸡
消费了第76只鸡
生产了第78只鸡
消费了第77只鸡
生产了第79只鸡
消费了第78只鸡
生产了第80只鸡
生产了第81只鸡
消费了第79只鸡
生产了第82只鸡
消费了第81只鸡
生产了第83只鸡
消费了第82只鸡
生产了第84只鸡
消费了第83只鸡
生产了第85只鸡
消费了第84只鸡
生产了第86只鸡
消费了第85只鸡
生产了第87只鸡
消费了第86只鸡
生产了第88只鸡
消费了第87只鸡
生产了第89只鸡
消费了第88只鸡
生产了第90只鸡
消费了第89只鸡
生产了第91只鸡
消费了第90只鸡
生产了第92只鸡
消费了第91只鸡
生产了第93只鸡
消费了第92只鸡
生产了第94只鸡
消费了第93只鸡
生产了第95只鸡
消费了第94只鸡
生产了第96只鸡
消费了第95只鸡
生产了第97只鸡
消费了第96只鸡
生产了第98只鸡
消费了第97只鸡
生产了第99只鸡
消费了第98只鸡
消费了第99只鸡
消费了第80只鸡

信号灯法(通过标志位):

标志位为 true,表示产品为空
当标志位为 true,生产者生产产品,并将标志位设为false,通知消费者消费
当标志位为 false,消费者消费产品,并将标志位设为true,通知生产者生产

public class TestPC2 {
	
	public static void main(String[] args) {
		TV tv = new TV();
		new Actor(tv).start();
		new Audience(tv).start();
		
	}

}

class Actor extends Thread{
	
	TV tv;
	
	public Actor(TV tv) {
		this.tv = tv;
	}
	
	@Override
	public void run() {
		for(int i=0;i<20;i++) {
			if(i%2==0) {
				this.tv.perform("节目");
			}else {
				this.tv.perform("广告");
			}
		}
	}
	
}

class Audience extends Thread{
	
	TV tv;
	
	public Audience(TV tv) {
		this.tv = tv;
	}
	
	@Override
	public void run() {
		for(int i=0;i<20;i++) {
			tv.watch();
		}
	}
	
}

class TV{
	
	String show;
	boolean flag = true;
	
	public synchronized void perform(String show) {
		
		if(!flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		System.out.println("演员表演了:"+show);
		this.show=show;
		this.notifyAll();
		this.flag = !this.flag;
	}
	
	public synchronized void watch() {
		if(flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("观众观看了:"+show);
		this.notifyAll();
		this.flag = !flag;
		
	}
	
}
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
演员表演了:节目
观众观看了:节目
演员表演了:广告
观众观看了:广告
  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页

打赏

BLUcoding

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值