1.wait和notify相關概念:
wait和notify方法是Java同步機制中重要的組成部分, 這些方法只有在Synchronized方法或Synchronized代碼塊中才能使用
否者就會報java.lang.IllegalMonitorStateExceprion異常
當Synchronized方法或者Synchronized代碼塊中的wait() 方法被調用時,當前線程將被中斷運行,並且放棄該對象鎖
當例外的線程執行了某個對象notify()方法后,會喚醒在此對象等待池中的某個線程使之成為可運行的(就緒狀態)線程。
notifuAll()方法會喚醒所有等待這個對象的線程使之成為可運行的線程。
2.下面通過一個比較經典的問題來講解着兩個方法:
問題描述:生產者將產品交給店員,,而消費者從店員處取走產品,店員一次只能持有固定數量的產品,如果生產者生產了過多的產品,
店員會叫生產者等一下;若果店中的有空位放產品了在通知生產者繼續生產;如果店中沒有產品了,店員會告訴消費者等一下,如果店中有產品
再通知生產者來取走產品。這里可能出現的問題有以下兩個:
- 生產者比消費者快時,消費者會漏掉一些數據沒有取到
- 消費者比生產者快時,消費者會取相同的數據
3.代碼如下:
1 public class ProductTest { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 8 Clerk clerk = new Clerk(); 9 Producter producter = new Producter(clerk); 10 Consumer consumer = new Consumer(clerk); 11 Thread thread1 = new Thread(producter); 12 thread1.setName("生產者"); 13 Thread thread2 = new Thread(consumer); 14 thread2.setName("消費者"); 15 thread1.start(); 16 thread2.start(); 17 18 } 19 20 public static class Clerk { 21 // 產品數量 22 int productNums = 0; 23 24 // 利用下城,增加產品數量,店員獲取到的數量達到100個后,將不會繼續增加。就等待消費者來取東西了 25 public synchronized void addProduct() { 26 27 if (productNums >= 20) { 28 try { 29 wait(); 30 } catch (InterruptedException e) { 31 e.printStackTrace(); 32 } 33 } else { 34 35 productNums = productNums + 1; 36 System.out.println(Thread.currentThread().getName() + ":" 37 + "添加了第" + productNums + "個產品"); 38 notifyAll();// 產品數量沒到上線,通知其他線程來進行存或則取 39 } 40 } 41 42 public synchronized void getProduct() { 43 if (productNums <= 0) { 44 try { 45 wait(); 46 } catch (InterruptedException e) { 47 e.printStackTrace(); 48 } 49 } else { 50 System.out.println(Thread.currentThread().getName() + ":" 51 + "買走了第" + productNums + "個產品"); 52 productNums = productNums - 1; 53 notifyAll();// 產品數量沒到下線,通知其他線程來進行存或則取 54 } 55 56 } 57 58 } 59 60 // 生產者要執行的線程 61 public static class Producter implements Runnable { 62 63 private Clerk clerk; 64 65 public Producter(Clerk clerk) { 66 this.clerk = clerk; 67 } 68 69 @Override 70 public void run() { 71 72 while (true) { 73 74 try { 75 // 不知道什么時候生產者回來添加產品,所以用一個隨機時間來讓進行線程隨眠,來模仿生產者來訪的不定時 76 Thread.sleep((int) (Math.random() * 10) * 100); 77 } catch (InterruptedException e) { 78 e.printStackTrace(); 79 } 80 81 clerk.addProduct(); 82 83 } 84 85 } 86 87 } 88 89 // 消費者需要執行的線程 90 public static class Consumer implements Runnable { 91 92 private Clerk clerk; 93 94 public Consumer(Clerk clerk) { 95 this.clerk = clerk; 96 } 97 98 @Override 99 public void run() { 100 101 while (true) { 102 103 try { 104 // 不知道什么時候消費者回來添加產品,所以用一個隨機時間來讓進行線程隨眠,來模仿消費者來訪的不定時 105 Thread.sleep((int) (Math.random() * 10) * 100); 106 } catch (InterruptedException e) { 107 e.printStackTrace(); 108 } 109 110 clerk.getProduct(); 111 112 } 113 114 } 115 } 116 117 }
運行后的結果一目了然:

