生产者消费者概述和案例演示

案例:牛奶工(生产者)送牛奶,送第几瓶奶时,消费者就接受第几瓶,比如送第一瓶奶,消费者就收到第一瓶奶。 使用奶箱(Milk Box)来作为共享数据区域。

那么在生产者类中就要有存储牛奶的方法,消费者就要有获取牛奶的方法。

奶箱类(Milk Box),需要对方法添加synchronized关键则,否则会发生异常,使用wait()方法来导致线程等待,使用notifyAll()方法来唤醒线程

public class MilkBox {
    //表示第几瓶奶
    private int milk;
    //定义一个成员变量,表示Milk Box的状态
    private boolean status = false;

    //存储牛奶方法
    public synchronized void put(int milk) {
        //如果有牛奶,等待消费者消费牛奶
        if (status) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果没有奶就生产奶
        this.milk = milk;
        System.out.println("送奶工正在将第" + this.milk + "瓶奶放入Milk Box");

        //生产完毕,改变Milk Box状态
        status = true;

        //唤醒其他等待的线程
        notifyAll();
    }

    //获取牛奶方法
    public synchronized void get() {
        //如果没有牛奶,等待生产
        if (!status) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //如果有牛奶,就消费牛奶
        System.out.println("用户拿到第" + this.milk + "瓶Milk");

        //消费完毕后,修改Milk Box状态
        status = false;

        //唤醒其他等待的线程
        notifyAll();
    }
}

生产者类(Producer)

public class Producer implements Runnable {
    private MilkBox mb;

    public Producer(MilkBox mb) {
        this.mb = mb;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            mb.put(i);
        }
    }
}

消费者类(Customer)

public class Customer implements Runnable {
    private MilkBox mb;

    public Customer(MilkBox mb) {
        this.mb = mb;
    }

    @Override
    public void run() {
        while (true) {
            mb.get();
        }
    }
}

奶箱测试类(MilkBoxDemo)

public class MilkBoxDemo {
    public static void main(String[] args) {
        //创建Milk Box对象,表示共享数据区域
        MilkBox mb = new MilkBox();
//
//        //创建生产者对象,把Milk Box对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
        Producer p = new Producer(mb);
//
//        //创建消费者对象,把Milk Box对象作为构造方法参数传递,因为在这个类中要调用获取牛奶的操作
        Customer c = new Customer(mb);
//
//        //创建2个线程对象,分别把生产者对象和消费者对新作为构造方法参数传递
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);
//
//        //启动线程
        t1.start();
        t2.start();

    }
}

运行结果:

猜你喜欢

转载自www.cnblogs.com/pxy-1999/p/12805053.html
今日推荐