某面試題,實現一個生產者——消費者模型
題目:采用多線程技術,通過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容器造成信號丟失,並不一定能通知到我們想要告知的線程。