java 线程(三) wait和notify方法

﹥>﹥吖頭↗ 提交于 2019-12-22 03:34:37
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 }

运行后的结果一目了然:

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!