关键词搜索

源码搜索 ×
×

(Java)生产者及消费者--引出问题

发布2020-01-17浏览454次

详情内容

在线程操作中有一个经典的案例程序,即生产者和消费者问题,生产者不断生产,消费者不断取走生产者生产的产品。

生产者生产出信息后将其放到一个区域中,消费者从此区域中取出数据,但是本程序牵扯到线程运行的不确定性,所以会存在两点问题:

(1)假设生产者线程刚向数据存储空间添加了信息的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把信息的名称和上一个信息的内容联系到一起

(2)生产者放了若干次的数据,消费者才开始取数据,或者是,消费者取完一个数据后,还没等到生产者放入新的数据,又重复取出已取过的数据。

一、程序的基本实现

因为程序中不断生产的是信息,而消费者不断取出的也是信息,所以定义一个保存信息的类:Info.java

class Info {
    private String name = "JAVA";//信息名称,指定默认值
    private String content = "LANGUAGE";//信息内容,指定默认值
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
    public String getContent(){
        return content;
    }
    public void setContent(String content){
        this.content = content;
    }
}

    Info 类的组成非常简单,只包含了用于保存信息名称的 name 属性 和用于保存信息内容的 content 属性,因为生产者和消费者要操作同一个空间的内容,所以生产者和消费者分别实现 Runnable 接口,并接收 Info 类的应用。

    二、生产者

    class Producer implements Runnable{//定义生产者线程
        private Info info = null;//保存 Info 引用
        public Producer(Info info){//通过构造方法设置 info 属性内容
            this.info = info;//为 info 属性初始化
        }
        public void run(){//覆写 run()方法
            boolean flag = false;//定义标记位
            for(int i=0;i<10;i++){
                if (flag){//如果为 TRUE,则设置第一个信息
                    this.info.setName("JAVA_1");//设置信息名称
                    try{
                        Thread.sleep(10);//加入延迟10
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    this.info.setContent("LANGUAGE_1");//设置信息内容
                    flag = false;//修改标记位
                }else {//如果为false,则设置第2 个信息
                    this.info.setName("JAVA_2");
                    try{
                        Thread.sleep(10);//加入延迟10
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    this.info.setContent("LANGUAGE_2");
                    flag = true;//修改标记位
                }
            }
        }
    }
    
      17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在生产者的构造方法中传入了 Info 类的实例化对象,然后在 run() 方法中循环10次以产生信息的具体内容。

    三、消费者

    class Consumer implements Runnable{//定义消费者线程
        private Info info = null;
        public Consumer(Info info){
            this.info = info;//通过构造方法设置 info 属性,为 info 属性初始化
        }
        public void run(){
            for(int i=0;i<10;i++){
                try{
                    Thread.sleep(20);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(this.info.getName() + " --> " + this.info.getContent());//取出信息
            }
        }
    }
    

      消费者线程类中也同样接收了一个 Info 对象的引用,并采用 10 此循环的方式信息并输出

      注意这里消费者代码中,延迟设置为20,就是为了产生当生产者添加了信息的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把信息和上一个信息的内容联系到一起

      四、测试程序

      public class ThreadCase {
          public static void main(String[] args) {
              Info i = new Info();
              Producer pro = new Producer(i);//实例化生产者,传递 Info 引用
              Consumer con = new Consumer(i);//实例化消费者,传递 Info 引用
              new Thread(pro).start();//启动生产者线程
              new Thread(con).start();//启动消费者线程
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      在这里插入图片描述

      相关技术文章

      点击QQ咨询
      开通会员
      返回顶部
      ×
      微信扫码支付
      微信扫码支付
      确定支付下载
      请使用微信描二维码支付
      ×

      提示信息

      ×

      选择支付方式

      • 微信支付
      • 支付宝付款
      确定支付下载