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 }
运行后的结果一目了然:
来源:https://www.cnblogs.com/liangstudyhome/p/4564780.html