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

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

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

(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;//修改标记位
            }
        }
    }
}

在生产者的构造方法中传入了 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();//启动消费者线程
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南淮北安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值