线程安全问题(3)--- wait(),notify()

前言

在多线程的环境下,我们常常要协调多个线程之间的执行顺序,而为了实现这一点,Java提供了一些方法来帮助我们完成这一点。


一,wait()

作用:

  1. 使当前线程进入等待状态 
  2. 释放当前的锁 (即该方法必须和 synchrnized 关键字一起使用)
  3. 等待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("等待后");
        }
    }
}

线程安全问题(3)--- wait(),notify()_第1张图片

 二,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();//那把锁调用,唤醒哪个wait
                System.out.println("44444");
            }
        });
        t1.start();
        t2.start();
    }
}

线程安全问题(3)--- wait(),notify()_第2张图片

补充:notifyAll()方法能一次唤醒所有等待的线程,但是这些线程之间会重新产生锁竞争,无法具体的决定线程的执行顺序,所以一般不推荐使用。

三,wait 和 sleep 的区别

相同点:

        都能使线程暂停一段时间。

不同点:

        1. wait 是 Object 类中的一个方法,sleep 是 Thread 类中的一个方法;

        2. wait 必须在 synchronized 修饰的代码块或方法中使用,sleep方法可以在任何位置使用;

        3. wait 被调用后当前线程进入BLOCK状态并释放锁,可以通过notify,notifyAll方法进行唤醒;sleep被调用后当前线程进入TIMED_WAIT状态,不涉及锁相关的操作;

你可能感兴趣的:(java,开发语言)