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