zoukankan      html  css  js  c++  java
  • 多线程:生产者消费者(管程法、信号灯法)

    1、生产者、消费者

    操作系统(生产者、消费者问题)

     

    2、管程法

    (1)创建生产者:

    public class Productor extends Thread{
        SynContainer synContainer;
        public Productor(SynContainer synContainer){
            this.synContainer=synContainer;
        }
        public void run(){
            for(int i=0;i<10;i++){
                synContainer.push(new Chicken(i));
                System.out.println("生产了"+i+"只鸡");
            }
        }
    }

    (2)创建消费者:

    public class Consume extends Thread {
        SynContainer synContainer;
        public Consume(SynContainer synContainer){
            this.synContainer=synContainer;
        }
        public void run(){
            for(int i=0;i<10;i++){
                System.out.println("消费了第"+i+"只鸡");
            }
        }
    }

    (3)创建产品类:

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

    (4)创建同步代码:

    public 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;
        }
    }

    保证容器中没有产品的时候生产产品,不能消费;容器中产品满了的时候,不能再去生产产品

    (5)创建测试类:

    public class Test {
        public static void main(String[] args) {
            SynContainer synContainer=new SynContainer();
            new Productor(synContainer).start();
            new Consume(synContainer).start();
        }
    }

    (6)测试:

    生产了0只鸡
    生产了1只鸡
    生产了2只鸡
    生产了3只鸡
    生产了4只鸡
    生产了5只鸡
    生产了6只鸡
    生产了7只鸡
    生产了8只鸡
    生产了9只鸡
    消费了第0只鸡
    消费了第1只鸡
    消费了第2只鸡
    消费了第3只鸡
    消费了第4只鸡
    消费了第5只鸡
    消费了第6只鸡
    消费了第7只鸡
    消费了第8只鸡
    消费了第9只鸡

    3、信号灯法

    (1)创建生产者:

    //生产者:演员
    public 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.play("猫和老鼠");
                }else {
                    this.tv.play("海绵宝宝");
                }
            }
        }
    }

    (2)创建消费者:

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

    (3)书写同步代码:

    //产品:节目
    public 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;
        }
    }

    (4)创建测试类:

    //通过标志位解决
    public class Test {
        public static void main(String[] args) {
            TV tv=new TV();
            new Player(tv).start();
            new Watcher(tv).start();
        }
    }

    (5)测试:

    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝
    演员表演了:猫和老鼠
    观看了猫和老鼠
    演员表演了:海绵宝宝
    观看了海绵宝宝

    (6)与管程法的最大不同就是,用信号灯法需要设置一个标志位,而管程法是设置一个变量,根据变量的值来进行

  • 相关阅读:
    fiddle 抓取PC端浏览器的Https请求和
    fiddle 截取手机日志如何设置
    APP(二)adb 日志分析
    APP(一) 测试知识点
    查询电脑IP地址
    接口是什么、常见接口类型/协议、常见的 http 状态码、剖析 cookie session、接口相关问题
    SQL 语句的执行顺序
    MySQL 数据库(三):查
    lr参数与C语言函数参数的区别
    使用jdk自带的visualVM监控远程监控was
  • 原文地址:https://www.cnblogs.com/zhai1997/p/13026704.html
Copyright © 2011-2022 走看看