多线程(11)线程通信

一:应用场景:生产者和消费者问题

①假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费

②如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止

③如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止。

二:分析

这是一个线程通信同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件

①对于生产者,没有生产产品之前,要通知消费者等待,而生产了产品之后,又需要马上通知消费者消费

②对于消费者,在消费之后,要通知生产者已经结束消费,需要生产新的产品以供消费

③在生产者消费者问题中,仅有synchronized是不够的

    synchronized可阻止并发更新同一个共享资源,实现同步

    synchronized不能用来实现不同线程之间的消息传递(通信)

三:java提供了几个方法解决线程之间的通信问题

①wait():表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁

②wait(long timeout);指定等待的毫秒数

③notify():唤醒一个处于等待状态的线程

④notifyAll();唤醒同一个对象上所有调用wait()方法的线程,优先级高的线程优先调度。

四:解决方式一(管程法)

①生产者:负责生产数据的模块

②消费者:负责处理数据的模块

③缓冲区:消费者不能直接使用生产者的数据,他们之间有个缓冲区

生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据

//测试:生产者消费者模型--》利用缓存区解决;管程法

//生产者,消费者,产品,缓存区
public class TestPro {
    public static void main(String[] args) {
        SynContainer synContainer=new SynContainer();
        new Product(synContainer).start();
        new Consumer(synContainer).start();
    }
}

//生产者
class Product extends  Thread {
    SynContainer container;

    public Product(SynContainer container) {
        this.container = container;
    }

    //生产
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            container.push(new Chickde(i));
            System.out.println("生产了" + i + "只鸡");
        }
    }
}
//消费者
class Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container){
        this.container=container;
    }
    //消费
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("消费了----"+container.pop().id+"只鸡");
        }
    }
}
//产品
class  Chickde{
    int id;
    Chickde(int id){
        this.id=id;
    }
}

//缓存区
class SynContainer{
    //需要一个容器大小
    Chickde[] chickdes=new Chickde[10];
    //容器计数器
    int  count=0;

    //生产者放入产品
    public  synchronized void push(Chickde chickde){
        //如果容器满了,就需要等待消费者
        if (count==chickdes.length){
            //通知消费者消费,生产等待
            try {
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //如果没有满,我们就需要丢入产品
        chickdes[count]=chickde;
        count++;

        //可以通知消费者消费了
        this.notifyAll();
    }
    //消费者消费产品
    public  synchronized Chickde pop(){
        //判断能否消费
        if (count==0){
            //等待生产者生产,消费者等待
            try{
                this.wait();

            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //如果可以消费
        count--;
        Chickde chickde=chickdes[count];

        //吃完了,通知生产者生产
        this.notifyAll();
        return  chickde;
    }
}
生产了0只鸡
生产了1只鸡
生产了2只鸡
生产了3只鸡
生产了4只鸡
生产了5只鸡
生产了6只鸡
生产了7只鸡
生产了8只鸡
生产了9只鸡
消费了----9只鸡
消费了----8只鸡
消费了----7只鸡
消费了----6只鸡
消费了----5只鸡
消费了----4只鸡
消费了----3只鸡
消费了----2只鸡
消费了----1只鸡
消费了----0只鸡
生产了10只鸡
生产了11只鸡
生产了12只鸡
生产了13只鸡
生产了14只鸡
生产了15只鸡
生产了16只鸡
生产了17只鸡
生产了18只鸡
生产了19只鸡
生产了20只鸡
消费了----10只鸡
消费了----20只鸡
消费了----19只鸡
消费了----18只鸡
消费了----17只鸡
消费了----16只鸡
消费了----15只鸡
消费了----14只鸡
消费了----13只鸡
消费了----12只鸡
消费了----11只鸡
生产了21只鸡
生产了22只鸡
生产了23只鸡
生产了24只鸡
生产了25只鸡
生产了26只鸡
生产了27只鸡
生产了28只鸡
生产了29只鸡
生产了30只鸡
生产了31只鸡
消费了----26只鸡
消费了----31只鸡
消费了----30只鸡
消费了----29只鸡
消费了----32只鸡
消费了----28只鸡
消费了----27只鸡
消费了----25只鸡
消费了----24只鸡
消费了----23只鸡
消费了----22只鸡
消费了----21只鸡
生产了32只鸡
生产了33只鸡
生产了34只鸡
生产了35只鸡
生产了36只鸡
生产了37只鸡
生产了38只鸡
生产了39只鸡
生产了40只鸡
生产了41只鸡
生产了42只鸡
消费了----42只鸡
消费了----41只鸡
消费了----40只鸡
消费了----39只鸡
消费了----38只鸡
消费了----37只鸡
消费了----36只鸡
消费了----35只鸡
消费了----34只鸡
消费了----33只鸡
生产了43只鸡
生产了44只鸡
生产了45只鸡
生产了46只鸡
生产了47只鸡
生产了48只鸡
生产了49只鸡
生产了50只鸡
生产了51只鸡
生产了52只鸡
消费了----52只鸡
消费了----51只鸡
消费了----50只鸡
消费了----49只鸡
消费了----48只鸡
消费了----47只鸡
消费了----46只鸡
消费了----45只鸡
消费了----44只鸡
消费了----43只鸡
生产了53只鸡
生产了54只鸡
生产了55只鸡
生产了56只鸡
生产了57只鸡
生产了58只鸡
生产了59只鸡
生产了60只鸡
生产了61只鸡
生产了62只鸡
消费了----62只鸡
消费了----61只鸡
消费了----60只鸡
消费了----59只鸡
消费了----58只鸡
生产了63只鸡
生产了64只鸡
生产了65只鸡
生产了66只鸡
消费了----63只鸡
消费了----67只鸡
消费了----66只鸡
消费了----65只鸡
消费了----64只鸡
消费了----57只鸡
消费了----56只鸡
消费了----55只鸡
消费了----54只鸡
消费了----53只鸡
生产了67只鸡
生产了68只鸡
生产了69只鸡
生产了70只鸡
生产了71只鸡
生产了72只鸡
生产了73只鸡
生产了74只鸡
生产了75只鸡
生产了76只鸡
生产了77只鸡
消费了----77只鸡
消费了----76只鸡
消费了----75只鸡
消费了----74只鸡
消费了----78只鸡
消费了----73只鸡
消费了----72只鸡
消费了----71只鸡
消费了----70只鸡
消费了----69只鸡
消费了----68只鸡
生产了78只鸡
生产了79只鸡
消费了----79只鸡
消费了----80只鸡
生产了80只鸡
生产了81只鸡
生产了82只鸡
生产了83只鸡
生产了84只鸡
生产了85只鸡
生产了86只鸡
生产了87只鸡
生产了88只鸡
生产了89只鸡
生产了90只鸡
消费了----90只鸡
生产了91只鸡
生产了92只鸡
消费了----91只鸡
消费了----92只鸡
生产了93只鸡
生产了94只鸡
消费了----93只鸡
消费了----94只鸡
生产了95只鸡
生产了96只鸡
消费了----95只鸡
消费了----96只鸡
生产了97只鸡
生产了98只鸡
消费了----97只鸡
消费了----98只鸡
生产了99只鸡
消费了----99只鸡
消费了----89只鸡
消费了----88只鸡
消费了----87只鸡
消费了----86只鸡
消费了----85只鸡
消费了----84只鸡
消费了----83只鸡
消费了----82只鸡
消费了----81只鸡

 

    解决方式二(信号灯法)

①通过一个标志位来判断

//测试生产者消费者问题2:信号灯法,标志位解决
public class TestPc2 {
	public static void main(String[] args) {
		TV tv=new TV();
		new Player(tv).start();
		new Watchrer(tv).start();
	}
}
//生产者---》演员
class Player extends Thread{
	TV tv;
	public  Player(TV tv){
		this.tv=tv;
	}
	@Override
	public void run() {
		for (int i=0;i<20;i++){
			if (i%2==0){
				this.tv.play("快乐大本营播放中");
			}else {
				this.tv.play("抖音:记录美好生活");
			}
		}
	}

}
//消费者--->观众
class Watchrer extends Thread{
 TV tv;
 public Watchrer(TV tv){
 	this.tv=tv;
 }
	@Override
	public void run() {
		for (int i=0;i<20;i++){
		tv.watch();
		}
	}

}

//观众---》节目
class TV{
	//演员表演 ,观众等待
	//观众观看,演员等待
	String  voice;//表演的节目
	boolean flag=true;
	//表演
	public  synchronized  void play(String voice){
		if (!flag){
			try {
				this.wait();
			}catch (InterruptedException e){
				e.printStackTrace();
			}
		}
		System.out.println("演员表演了:"+voice);
		//通知观众观看
		this.notifyAll();//通知唤醒
		this.voice=voice;
		this.flag=!this.flag;
	}
	//观看
	public synchronized void watch(){
		if (flag){
			try{
				this.wait();
			}catch (InterruptedException e){
				e.printStackTrace();
			}
		}
		System.out.println("观看了:"+voice);
		//通知演员表演
		this.notifyAll();
		this.flag=!this.flag;
	}
}
演员表演了:快乐大本营播放中
观看了:快乐大本营播放中
演员表演了:抖音:记录美好生活
观看了:抖音:记录美好生活
演员表演了:快乐大本营播放中
观看了:快乐大本营播放中
演员表演了:抖音:记录美好生活
观看了:抖音:记录美好生活
演员表演了:快乐大本营播放中
观看了:快乐大本营播放中
演员表演了:抖音:记录美好生活
观看了:抖音:记录美好生活
演员表演了:快乐大本营播放中
观看了:快乐大本营播放中

 

posted @ 2021-05-03 12:01  iLisa  阅读(102)  评论(0编辑  收藏  举报