某面试题,实现一个生产者——消费者模型
题目:采用多线程技术,通过wait/notify,设计实现一个符合生产者和消费者问题的程序,对某一个对象(枪膛)进行操作,其最大容量是20颗子弹,生产者线程是一个压入线程,它不断向枪膛中压入子弹,消费者线程是一个射出线程,它不断从枪膛中射出子弹。
public class Test { public Queue<Integer> gun = new LinkedList<Integer>(); // 枪 public final int maxCount = 20; // 枪里面最多上20发子弹 public final int maxbulletCount = 200; // 枪里面最多上20发子弹 public final int[] bullets = new int[maxbulletCount]; private int pos = 0; public Test() { Random r = new Random(); for (int i = 0; i < maxbulletCount; i++) { bullets[i] = r.nextInt(1000); } } private int getBullet() { return pos < maxbulletCount ? bullets[pos++] : -1; } class Producer implements Runnable { @Override public void run() { while (true) { synchronized (gun) { try { if(gun.size() == maxCount){ System.out.println("*********** 枪膛已经上满子弹"); gun.wait(); } else { int i = getBullet(); if (i == -1) { System.out.println("*********** 子弹已经用完"); Thread.interrupted(); } else { gun.add(i); System.out.println("*********** 子弹" + i + "上膛 枪里面还有" + gun.size() + "颗子弹"); try { Thread.sleep(199); } catch (InterruptedException e) { e.printStackTrace(); } } } gun.notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class Consumer implements Runnable { public void run() { while (true) { synchronized (gun) { try { if( gun.size() == 0 ){ System.out.println("*********** 枪没子弹了 "); gun.wait(); } else { Integer bullet = gun.poll(); System.out.println("*********** 使用子弹" + bullet + ", 枪里面还有" + gun.size() + "颗子弹"); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } gun.notifyAll(); } catch (Exception e) { e.printStackTrace(); } } } } } public static void main(String[] args) { Test t = new Test(); Thread p = new Thread(t.new Producer()); Thread c = new Thread(t.new Consumer()); p.start(); c.start(); } }
值得注意的是:notify并不释放锁,只是唤醒其他线程来竞争锁,当synchronized代码执行完才释放锁。一般建议使用notifyAll,不使用notify,因为notify容器造成信号丢失,并不一定能通知到我们想要告知的线程。