上⾯⼀种基于“锁”的⽅式,线程需要不断地去尝试获得锁,如果失败了,再继续尝试。这可能会耗费服务器资源。⽽等待/通知机制是另⼀种⽅式。Java
多线程的等待/通知机制是基于Object
类的wait()
⽅法和notify()
,notifyAll()
⽅法来实现的。
[alt type="success"]
notify()⽅法会随机叫醒⼀个正在等待的线程,⽽notifyAll()会叫醒所有正在等待的线程。
[/alt]
前⾯我们讲到,⼀个锁同⼀时刻只能被⼀个线程持有。⽽假如线程A现在持有了⼀个锁lock
并开始执⾏,它可以使⽤lock.wait()
让⾃⼰进⼊等待状态。这个时候,lock
这个锁是被释放了的。这时,线程B获得了lock
这个锁并开始执⾏,它可以在某⼀时刻,使
⽤lock.notify()
,通知之前持有lock
锁并进⼊等待状态的线程A,说“线程A你不⽤等了,可以往下执⾏了”。
[alt type="warning"]
需要注意的是,这个时候线程B并没有释放锁lock
,除⾮线程B这个时候使⽤lock.wait()
释放锁,或者线程B执⾏结束⾃⾏释放锁,线程A才能得到lock
锁。
[/alt]
package com.company;
import java.util.stream.IntStream;
public class WaitAndNotify {
private static Object lock = new Object();
static class ThreadA implements Runnable{
@Override
public void run() {
synchronized (lock){
IntStream.range(1,5).forEach(i->{
System.out.println("ThreadA:"+i);
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
static class ThreadB implements Runnable{
@Override
public void run() {
synchronized (lock){
IntStream.range(1,5).forEach(i->{
System.out.println("ThreadB:"+i);
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
public static void main(String[] args) throws InterruptedException {
new Thread(new ThreadA()).start();
Thread.sleep(1000);
new Thread(new ThreadB()).start();
}
}
[alt type="info"]
需要注意的是等待/通知机制使⽤的是使⽤同⼀个对象锁,如果你两个线程使⽤的是不同的对象锁,那它们之间是不能⽤等待/通知机制通信的。
[/alt]
感谢分享