关于Java多线程生产者消费者实例

实例题目:

1.在一个KFC内,服务员负责生产食物,消费者负责消费食物;

2.当生产到一定数量可以休息一下,直到消费完食物,再马上生产,一直循环
程序涉及到的内容:

1.这设计到java模式思想:生产者消费者模式

2.要保证操作对象的统一性,即消费者和服务者都是跟同一个KFC发生关系的,KFC只能new一次

3.this.notifyAll();和 this.wait();一个是所有唤醒的意思,一个是让自己等待的意思;

比如本题中,生产者生产完毕后,先所有唤醒(包括消费者和生产者),再让所有自己(生产者)等待

这时,消费者开始消费,直到食材不够,先所有唤醒(包括消费者和生产者),再让所有自己(消费者)等待

一直执行上面的操作的循环

4.生产者和消费者都要继承Thread,才能实现多线程的启动

程序设计的步骤思路:

1.创建一个食物类Food,有存放/获取食物的名称的数量

2.创建一个KFC类,有生产食物和消费食物的方法

3.创建一个客户类Customer,继承Thread,重写run方法,在run方法里面进行消费食物操作

4.创建一个服务员类Produce,继承Thread,重写run方法,在run方法里面进行生产食物的操作

5.创建主方法的调用类

Food类

public class Food {

    public final static int max = 20;//大于最大食材数,生产者释放锁,处于等待状态
    public final static int min = 5;//小于最小食材数,消费者释放锁,处于等待状态
    public static int hamburger = 20;//初始食材数

}

KFC类

public class KFC {

    public void produce(int index, String name) {
        try {
            synchronized (this) {
    //notifyAll和wait需要在锁内,否则调用方法时会报获取对象异常
                this.notifyAll();
                    Food.hamburger = Food.hamburger + index;
                    System.out.println("食材补充了" + index + ",生产者为" + name+ ",剩余总量为" + Food.hamburger);

                if (Food.hamburger >= Food.max) {
                    System.out.println("食材剩余总量充足,暂停生产");
                    // 使用wait时,需要保证此线程正在使用
                    this.wait(100);
                }
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public void custom(int index, String name) {
        try {
            synchronized (this) {
            //唤醒所有线程,允许获取锁
                this.notifyAll();

                    Food.hamburger = Food.hamburger - index;
                    System.out.println("食材消耗了" + index + ",消费者为" + name+ ",剩余总量为" + Food.hamburger);

                if (Food.hamburger <= Food.min) {
                    System.out.println("食材剩余不足,请及时生产生产");

                //释放当前线程锁,并休眠
                    this.wait(100);
                }
            }

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

Customer类

public class Customer extends Thread {

    public KFC kfc;
    public String name;

    public  Customer(KFC kfc,String name){
        this.kfc=kfc;
        this.name=name;
    }

    public void run(){
    //食材数大于最小食材数时可以进行消费
        while (Food.hamburger > Food.min) {
        kfc.custom(3, name);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
    }


}

Produce类

public class Produce extends Thread {

    public KFC kfc;
    public String name;

    public  Produce(KFC kfc,String name){
        this.kfc=kfc;
        this.name=name;
    }

    public void run(){
    //当食材数小于最大食材数时,就可以进行生产
        while (Food.hamburger < Food.max) {
        kfc.produce(5, name);
        try {
        //此线程休眠1秒,否则会造成都是同一个人生产的结果
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
    }

}

主函数调用类

public class Main {
    //生产者消费者例子
    public static void main(String[] arg0){

    // 只实例化一个KFC对象,保证每一个服务员和用户在同一个KFC对象内
    KFC kfc = new KFC();

    //实例化2个客户对象
    Customer c1 = new Customer(kfc,"客户A");
    Customer c2 = new Customer(kfc,"客户B");


    //实例化2个服务员对象
    Produce waiter1 = new Produce(kfc,"生产者A");
    Produce waiter2 = new Produce(kfc,"生产者B");


    //让所有的对象的线程都开始工作
    waiter1.start();
    waiter2.start();

    c1.start();
    c2.start();
  }
}

最终效果

这里写图片描述

发布了21 篇原创文章 · 获赞 15 · 访问量 4万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览