案例:牛奶工(生产者)送牛奶,送第几瓶奶时,消费者就接受第几瓶,比如送第一瓶奶,消费者就收到第一瓶奶。 使用奶箱(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(); } }
扫描二维码关注公众号,回复:
11152911 查看本文章
运行结果: