热狗生产者消费者问题

定义一个集合模拟长条容器存放热狗,集合里实际存放Integer,其值代表热狗的编号(热狗编号规则举例:300002代表编号为3的厨师做的第2个热狗),这样能通过集合添加和删除,实现先进先出;
以热狗集合作为对象锁,所有对热狗集合的操作(在长条容器中添加、取走热狗)互斥,这样保证不会出现多个顾客同时取最后剩下的一个热狗的情况,也不会出现多个厨师同时添加热狗造成长条容器里热狗数大于10个的情况;
当厨师希望往长条容器中添加热狗时,如果发现长条容器中已有10个热狗,则停止做热狗,等待顾客从长条容器中取走热狗的事件发生,以唤醒厨师可以重新进行判断,是否需要做热狗;
当顾客希望往长条容器中取走热狗时,如果发现长条容器中已没有热狗,则停止吃热狗,等待厨师往长条容器中添加热狗的事件发生,以唤醒顾客可以重新进行判断,是否可以取走热狗吃;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: Ren
 * @date: 2020-08-02  17:26
 * @description:
 */
public class TestProdCons {
    //定义一个存放热狗的集合,里面存放的是整数,代表热狗编号
    private static final List<Integer> hotDogs = new ArrayList<Integer>();

    public static void main(String[] args) throws InterruptedException {
        for (int i = 1; i <4; i++) {
            new Producer(i).start();
        }
        for (int i = 1; i <6 ; i++) {
            new Consumer(i).start();
        }
        Thread.sleep(2000);
//        将异常抛给虚拟机
        System.exit(0);
    }
    //生产者线程,以热狗集合作为对象锁,所有对热狗集合的操作互斥
    private static class  Producer extends  Thread{
        int i =1;
        int pid = 1;

        public Producer(int id) {
            this.pid= id;
        }

        public void run() {
            while (true) {
                //模拟消耗的时间
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (hotDogs) {
                    if (hotDogs.size() < 10) {
                        //热狗编号,300002代表编号为3的生产者生产的第2个热狗
                        hotDogs.add(pid*10000+i);
                        System.out.println("生产者" + pid + "生产热狗,编号为:" + (pid * 10000 + i));
                        i++;
                        hotDogs.notifyAll();
                    }else{
                        System.out.println("热狗数已经够十个,等待消费!");
                        try {
                            hotDogs.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    //消费者线程,以热狗集合作为对象锁,所有对热狗集合的操作互斥
    private static class Consumer extends Thread {
        int cid = 1;
//        初始化构造器
        public Consumer(int id) {
            this.cid = id;
        }

        public void run() {
            while (true) {
                try {
                    //模拟消耗的时间
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (hotDogs) {
                    if (hotDogs.size() > 0) {
                        System.out.println("消费者" + this.cid + "正在消费一个热狗,热狗编号为:" + hotDogs.remove(0));
//                        唤醒所有等待的线程
                        hotDogs.notifyAll();
                    } else {
                        System.out.println("吃tm太快了,wait...!");
                        try {
                            hotDogs.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}


在这里插入图片描述

Java提供了wait()、notify()、notifyAll()三个方法,解决线程之间协作的问题。这三个方法均是java.lang.Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常。

void wait():当前线程等待,等待其他线程调用此对象的 notify() 方法或 notifyAll() 方法将其唤醒。
void notify():唤醒在此对象锁上等待的单个线程。
void notifyAll():唤醒在此对象锁上等待的所有线程

猜你喜欢

转载自blog.csdn.net/weixin_44281922/article/details/107749303
今日推荐