基于java中的多线程应用原型-生产者和消费者模型的应用实例


前言

利用线程同步和线程通信实现这样一个过程:有一个煎饼摊,规定每天只做10个煎饼,卖完才能收摊,并且要保证任意时刻煎饼摊的煎饼数不能超过3个,如果顾客来的时候煎饼数为0,那么该顾客就要等待煎饼做好才能购买。利用线程来模拟这样一个过程,要求:打印出从开始制作煎饼到10个煎饼全部卖完的整个过程。
输出样例:
在这里插入图片描述

一、关键技术

线程同步,线程通信,生产者-消费者模型,共享数据类,共享数据控制类

二、步骤

1.创建共享数据类

设置一个共享数据类(有点像是利用全局变量来计数,只不过将变量封装在类中)
代码如下(示例):

//共享数据类,其中的数据都是作为共享数据,方便共享数据控制类的访问
public class Mycake {
    public int count = 0;  //记录当天做的煎饼数
    public int sell = 0;    //记录当天卖出的煎饼数
    
    public Mycake() {
    }
}

2.创建一个共享数据控制类

共享数据控制类,对共享数据类中的变量值进行修改
代码如下(示例):

//共享数据控制类,对做煎饼和卖煎饼过程的控制
class Sharecake {  //控制煎饼的制作和出售
    public Mycake mycake;
    public int flag = 0;  //标志,记录当前还有几个煎饼

    Sharecake() {
    }

    public synchronized void setSharecake(Mycake mycake) {   //该方法控制煎饼的制作
        //定义为同步方法,保证在同一个时刻只能有一个线程访问该方法
        if (this.flag == 3) {
            try {
                System.out.println("还有三个煎饼未出售,请卖出后再制作");
                this.wait();   //让生产者线程休眠,等待唤醒
            } catch (InterruptedException var3) {
            }
        }
        //当剩余的煎饼少于三个时,正常制作煎饼
        this.mycake = mycake;
        ++this.flag;
        ++mycake.count;
        this.notify();  //制作完成,唤醒消费者线程
    }

    public synchronized Mycake getSharecake() {  //该方法控制煎饼的出售
        if (this.flag == 0) {
            try {
                System.out.println("抱歉,没有做好的煎饼,顾客需要等待");
                this.wait();  //让消费者线程等待
            } catch (InterruptedException var2) {
            }
        }
        //正常售出煎饼
        --this.flag;
        ++this.mycake.sell;
        this.notify();  //卖出煎饼,唤醒生产者线程
        return this.mycake;
    }
}

3.定义一个生产者类

生产者线程,判断该不该生产
代码如下(示例):

class Producer implements Runnable {  //商家完成做煎饼的动作,所以使用控制类中的做煎饼的动作(方法)
    private static final int MAKE = 1000;  //自定义的休眠时间
    private Sharecake s;

    Producer(Sharecake s) {
        this.s = s;
    }

    public void run() {
        Mycake mycake = new Mycake();

        do {
            try {
                Thread.sleep(MAKE);
            } catch (InterruptedException var3) {
            }

            this.s.setSharecake(mycake);
            System.out.println("做好了一个煎饼,这是今天做的第" + mycake.count + "个煎饼");
        } while(mycake.count < 10);

        System.out.println("今天的10个煎饼已经制作完成!");
    }
}

4.定义一个消费者类

消费者线程,判断顾客是否需要等待,还是可以直接购买
代码如下(示例):

class Consumer implements Runnable {  //顾客消费,使用控制类中的出售动作(方法)
    Sharecake s;

    Consumer(Sharecake s) {
        this.s = s;
    }

    public void run() {
        Mycake mycake;
        do {
            try {
                Thread.sleep((long)((int)(Math.random() * 10000)));
                //利用随机函数来产生休眠时间来模拟顾客的不确定性
            } catch (InterruptedException var3) {
            }

            mycake = this.s.getSharecake();
            System.out.println("卖出一个煎饼,还剩" + this.s.flag + "个煎饼,这是今天卖出的第" + mycake.sell + "个煎饼");
        } while(mycake.sell >= 0 && mycake.sell < 10);

        System.out.println("今天的10个煎饼已经制作完成,可以收摊了!");
    }
}

5.主函数

逻辑控制

package com.company;

public class Main {

    public static void main(String[] args) {
	Sharecake s=new Sharecake();  //控制对象
	Producer p=new Producer(s);	
	Consumer c=new Consumer(s);
	Thread thread1=new Thread(p); //创建一个生产者线程
	Thread thread2=new Thread(c);
	thread1.start();
	thread2.start();
    }
}

总结

以上就是今天要讲的内容,本文利用生产者消费模型简单的介绍了如何实现线程之间的通信。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值