多线程-线程协作(七)

多线程-线程协作(七)

  1. 生产者消费者模式(不是一个模式,而是一个问题

    应用场景:你(消费者),肯德基店(缓存区),炸鸡员(生产者)

    • 你去肯德基店买炸鸡,肯德基店下单,炸鸡员就炸鸡,但是如果肯德基店如果已经有炸好的鸡,你就可以直接买走,你就不需要等待,炸鸡员就不用炸鸡,,但是如果肯德基店没有炸好的鸡,就要通知炸鸡员炸鸡,你就要等待。
    • 你和炸鸡员就类似两个线程,肯德基店就类似于缓存区,你和炸鸡员就跟肯德基店就会有线程通信。
  2. 线程通信-分析

    • 这是一个线程同步的问题,生成者和消费者共享一个资源,并且生成者和消费者之间相互依赖,互为条件。
    • 对于生产者,没有生产产品之前,要通知消费者等待,而生产了产品之后,又需要马上通知消费者消费。
    • 对于消费者,在消费之后,要通知生产者已经结束消费,需要生成新的产品以供消费。
    • 生产者消费者问题,仅有synchronized是不够的
      • synchronized可阻止并发更新同一个共享资源,实现了同步
      • synchronized 不能用来实现不同线程之间的消息传递
  3. 线程通信

    java提供了几个方法解决线程之间额通信问题
    在这里插入图片描述

  4. 解决方式1

    并发协作模式"生产者/消费者模式"—>管程法

    • 生产者:负责生产数据的模块(可能是方法,对象,线程,进程)
    • 消费者:负责处理数据的模块(可能是方法,对象,线程,进程)
    • 缓冲区:消费者不能直接使用生产者的数据,他们之间有个"缓冲区"

    生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据
    在这里插入图片描述

  5. 解决方式1,具体的代码实现

    //测试:生产者消费者模型--->利用缓冲区解决:管程法
    //生产者,消费者,产品,缓冲区
    public class TestPC {
          
          
        public static void main(String[] args) {
          
          
            SynContainer container=new SynContainer();
    
            new Productor(container).start();
            new Consumer(container).start();
        }
    }
    
    //生产者
    class Productor extends Thread{
          
          
        SynContainer container;//都需要用到缓冲区
        public Productor(SynContainer container){
          
          
            this.container=container;
        }
    
        //生产
        @Override
        public void run() {
          
          
            for (int i = 0; i < 100; i++) {
          
          
                container.push(new Chicken(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 Chicken{
          
          
        int id;//产品编号
        public Chicken(int id){
          
          
            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 ;
    
        }
    }
    
  6. 并发协作模型"生产者/消费者模式"—>信号灯法(逻辑是和管程法一样的只是解决的方式不一样).

    //测试生成者消费者问题2:信号灯法,标志位解决
    public class TestPC2 {
          
          
        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;
        }
    
        @Override
        public void run() {
          
          
            for (int i = 0; i < 20; i++) {
          
          
                if (i%2==0){
          
          
                    this.tv.play("快乐大本营播放中");
                }else {
          
          
                    this.tv.play("抖音:记录美好生活");
                }
            }
        }
    }
    
    //消费者-->观众
    class Watcher extends Thread{
          
          
        TV tv;
        public Watcher(TV tv){
          
          
            this.tv=tv;
        }
    
        @Override
        public void run() {
          
          
            for (int i = 0; i < 20; i++) {
          
          
                tv.watch();
            }
        }
    }
    
    //产品-->节目
    class TV{
          
          
         //演员表演,观众等待 T
        //观众观看,演员等待  F
        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;//我的标志位就要改变,保证它是最新的
        }
    }
    

猜你喜欢

转载自blog.csdn.net/Xun_independent/article/details/115015035