java 線程(三) wait和notify方法


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 }

運行后的結果一目了然:

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM