ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

二十五、生产者消费者问题

2022-05-20 19:03:08  阅读:155  来源: 互联网

标签:消费者 生产者 线程 二十五 new public synContainer


线程通信:

  • 应用场景:生产者和消费者问题
    • 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库﹐消费者将仓库中产品取走消费
    • 如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止
    • 如果仓库中放有产品,则消费者可以将产品取走消费﹐否则停止消费并等待,直到仓库中再次放入产品为止
  • 分析:这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件
    • 对于生产者,没有生产产品之前,要通知消费者等待.而生产了产品之后﹐又需要马上通知消费者消费

    • 对于消费者﹐在消费之后,要通知生产者已经结束消费

    • 需要生产新的产品以供消费.在生产者消费者问题中

    • 仅有synchronized是不够的

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

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

  • Java提供了几个方法解决线程之间的通信问题。注意:均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常lllegalMonitorStateException
方法名 作用
wait() 表示线程一直等待﹐直到其他线程通知,与sleep不同,会释放锁
wait(long timeout) 指定等待的毫秒数
notify() 唤醒一个处于等待状态的线程
notifyAll() 唤醒同一个对象上所有调用wait()方法的线程﹐优先级别高的线程优先调度

 

  • 并发协作模型“生产者/消费者模式”:生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据
    • 生产者:负责生产数据的模块(可能是方法﹐对象﹐线程﹐进程);
    • 消费者:负责处理数据的模块(可能是方法﹐对象,线程,进程);
    • 缓冲区:消费者不能直接使用生产者的数据﹐他们之间有个“缓冲区;
      • 解决方式1:管程法(缓冲区)

        

        

public class ProducersAndConsumers {
    public static void main(String[] args) {

        SynContainer synContainer = new SynContainer();

        Producers p = new Producers(synContainer);
        Consumers c = new Consumers(synContainer);

        new Thread(p).start();
        new Thread(c).start();
    }
}


//生产者
class Producers implements Runnable {

    SynContainer synContainer;

    public Producers(SynContainer synContainer) {
        this.synContainer = synContainer;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                synContainer.push(i);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

//消费者
class Consumers implements Runnable {

    SynContainer synContainer;

    public Consumers(SynContainer synContainer) {
        this.synContainer = synContainer;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                synContainer.pop(i);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

//产品
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(int i) throws InterruptedException {
        while (chickens.length == count) {
            this.wait();
        }
        Chicken chicken = new Chicken(i);
        chickens[count] = chicken;
        count++;
        System.out.println("生产第" + i + "只鸡");
        this.notifyAll();
    }

    //消费
    public synchronized void pop(int i) throws InterruptedException {
        while (count == 0) {
            this.wait();
        }
        //模拟延迟消费
        Thread.sleep(100);
        count--;
        System.out.println("消费第" + i + "只鸡");
        Chicken chicken = chickens[count];
        this.notifyAll();
    }
}

        

      • 解决方式2:信号灯法(标志位)

        

public class ProducersAndConsumers2 {
    public static void main(String[] args) {

        Product product = new Product();

        Producers2 p = new Producers2(product);
        Consumers2 c = new Consumers2(product);

        new Thread(p).start();
        new Thread(c).start();
    }
}


//生产者
class Producers2 implements Runnable {

    Product product;

    public Producers2(Product product) {
        this.product = product;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                product.push(i);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

//消费者
class Consumers2 implements Runnable {

    Product product;

    public Consumers2(Product product) {
        this.product = product;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                product.pop(i);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}


//缓冲区
class Product {

    //产品
    int id;

    //标志位
    boolean flag = false;

    //生产
    public synchronized void push(int id) throws InterruptedException {
        while (flag) {
            this.wait();
        }
        this.flag = !this.flag;
        System.out.println("生产了" + id + "号");
        this.notifyAll();
    }

    //消费
    public synchronized void pop(int id) throws InterruptedException {
        while (!flag) {
            this.wait();
        }
        this.flag = !this.flag;
        System.out.println("消费了" + id + "号");
        this.notifyAll();
    }
}

 

标签:消费者,生产者,线程,二十五,new,public,synContainer
来源: https://www.cnblogs.com/epiphany8/p/16293446.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有