文章目录
1 wait/notify 机制的原理
1.1 wait()方法是Object 类的方法,它的作用是使当前执行wait()方法的线程等待,在wait()所在的代码行处暂停执行,并释放锁,直到接到通知或中断。
1.2 notify()方法用来通知那些可能等待该锁的其他线程,如果有多个线程等待,则按照执行wait方法的顺序发出一次性通知(一次只能通知一个!),使得等待排在第一顺序的线程获得锁。需要说明的是,执行notify方法后,当前线程并不会立即释放锁,要等到程序执行完,即退出synchronized同步区域后。
总结:wait 方法使线程暂停运行,而notify 方法通知暂停的线程继续运行。
要想正确使用wait/notify,一定要注意:
wait/notify在调用前一定要获得相同的锁,如果在调用前没有获得锁,程序会抛出异常,也就调用不了wait/notify;另外,如果获得的不是同一把锁,notify不起作用。
2 wait() 方法的基本使用
2.1 在使用前没有获得锁,抛出异常
public class Test {
public static void main(String[] args) throws Exception {
try {
Object object = new Object();
object.wait();
}catch (Exception e) {
e.printStackTrace();
}
}
}
2.2 在使用前先获得锁,正确调用wait,无异常抛出
public class Test {
public static void main(String[] args) throws Exception {
try {
Object object = new Object();
System.out.println("执行wait之前的代码");
//获得锁
synchronized(object) {
object.wait();
System.out.println("执行wait之后的代码");
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
3 完整实现 wait/notify
3.1 创建Service类
public class Service {
Object lock = new Object();
public void waitMethod() {
synchronized(lock) {
try {
System.out.println(Thread.currentThread().getName()+"执行了wait方法,释放了锁");
lock.wait();
System.out.println(Thread.currentThread().getName()+"被唤醒了");
}catch (Exception e) {
e.printStackTrace();
}
}
}
public void notifyMethod() {
synchronized(lock) {
try {
System.out.println(Thread.currentThread().getName()+"执行了notify方法");
lock.notify();;
System.out.println(Thread.currentThread().getName()+"继续执行notify后的代码,完事后才释放锁");
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
3.2 创建ThreadA线程类
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.waitMethod();
}
}
3.3 创建ThreadB线程类
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.notifyMethod();
}
}
3.4 测试与分析
public class Test {
public static void main(String[] args) throws Exception {
Service service = new Service();
ThreadA threadA= new ThreadA(service);
ThreadB threadB= new ThreadB(service);
threadA.setName("A");
threadB.setName("B");
threadA.start();
threadB.start();
}
}
分析:
1、线程ThreadA启动后,获得lock锁,成功执行了wait方法,在wait方法所在行暂停,并且释放了锁
2、线程ThreadB获得ThreadA释放的锁,成功执行了notify方法并且通知到了ThreadA,告诉它做好苏醒准备,但ThreadB并没有马上释放锁,它继续执行,直到退出synchronzied 代码块
3、ThreadB退出synchronized 代码块后释放锁,ThreadA获得锁,从暂停的地方往后执行,直到程序执行完毕