wait和notify总结
十月 29, 2020
直接上结论
首先这两个东西必须在synchronized里面使用,要用到别的锁会有替代下面两个的东西。
- wait:挂起当前线程,释放获取到的锁,直到别的线程调用了这个对象的notify或notifyAll方法。wait被唤醒后会根据LIFO原则获得锁(不同虚拟机实现不同,Hotspot是LIFO)。
- notify:唤醒因调用wait挂起的线程,如果有多个线程,随机唤醒一个,注意notify不会立即释放锁,在退出锁代码块之后才释放。
其他内置锁
需要利用condition实现wait和notify。1
2
3Condition condition = lock.newCondition();
condition.await();
condition.siginal();多线程例题
一、wait和notify。
两个线程,线程一添加十个元素到容器里面,线程二监控元素的个数,当个数达到五个的时候线程二给出提示。
先看代码思路:用wait和notify解决,t2先wait,当t1添加五个数时候,notify,但是notify不会立即释放锁,所以再让t1wait,此时t2继续运行,打印输出,并且notify唤醒t1。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43public class TestMain {
static List list = new ArrayList();
public static void main(String[] args) {
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++) {
list.add(i);
System.out.println("add "+i);
if (list.size() == 5) {
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
//if (list.size() != 5) {//可有可无
try {
lock.wait();
System.out.println("output!!!!!");
lock.notify();//在哪notify都一样了,也可以放在锁外边
} catch (InterruptedException e) {
e.printStackTrace();
}
//}
}
}
});
t2.start();
t1.start();
}
}二、生产者消费者
实现一个固定容量的容器,拥有put、get、getCount方法。能支持2个生产者线程和10个消费者进程的阻塞调用。
第一版代码
container:
1 | class Container{ |
main:
1 | public class TestMain { |
第一版代码利用wait和notifyAll实现同步,当满了之后生产者wait,容器里面没东西,消费者wait。
注意这里面最后唤醒线程都用的是notifyAll,但是生产者和消费者都在同一个队列里面等着,notifyAll会同时通知所有人,而我们只想让消费者唤醒生产者,而不唤醒消费者,对于生产者也同理。
第二版
1 | class Container2 { |
换用ReentrantLock实现同步。用Condition实现wait和notify,condition把原来的一个等待队列分为了两个,所以每次只需要notify对应的就行。
查看评论