前言
在多线程的环境下,我们常常要协调多个线程之间的执行顺序,而为了实现这一点,Java提供了一些方法来帮助我们完成这一点。
一,wait()
作用:
- 使当前线程进入等待状态
- 释放当前的锁 (即该方法必须和 synchrnized 关键字一起使用)
- 等待notify()方法来唤醒,并重新获取该锁
注意:1. wait()方法同样会被 interrupted 方法中断,从而抛出 InterruptedException 异常
2. wait()方法不是说让调用该方法的线程去 "往前插队" 来调整顺序,而是让调用的线 程等待,让其他线程先执行来调整顺序。
代码如下:
public class Demo {public static void main(String[] args) throws InterruptedException {Object locker = new Object();synchronized (locker){System.out.println("等待前");locker.wait();//那个锁调用,就释放哪把锁System.out.println("等待后");}}
}
二,notify()
作用:唤醒等待的线程。
注意:
- notify() 只能唤醒一个等待线程,当有多个线程等待时,会随机挑选一个等待线程并将其唤醒(即没有先来后到)
- notify()方法执行完,不会立刻释放该锁,而是要等到该调用notify()方法的线程执行结束,才会释放锁
代码如下:
public class Demo1 {public static void main(String[] args) {Object locker = new Object();Thread t1 = new Thread(() -> {synchronized (locker){System.out.println("1111");try {locker.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("2222");}});Thread t2 = new Thread(() -> {synchronized (locker){System.out.println("33333");locker.notify();//那把锁调用,唤醒哪个waitSystem.out.println("44444");}});t1.start();t2.start();}
}
补充:notifyAll()方法能一次唤醒所有等待的线程,但是这些线程之间会重新产生锁竞争,无法具体的决定线程的执行顺序,所以一般不推荐使用。
三,wait 和 sleep 的区别
相同点:
都能使线程暂停一段时间。
不同点:
1. wait 是 Object 类中的一个方法,sleep 是 Thread 类中的一个方法;
2. wait 必须在 synchronized 修饰的代码块或方法中使用,sleep方法可以在任何位置使用;
3. wait 被调用后当前线程进入BLOCK状态并释放锁,可以通过notify,notifyAll方法进行唤醒;sleep被调用后当前线程进入TIMED_WAIT状态,不涉及锁相关的操作;