一、wait() 和 notify() 是什么?

wait() 和 notify() 是Object类中的方法。

由于线程之间是抢占式执⾏的,因此线程之间执⾏的先后顺序难以预知.
但是实际开发中有时候我们希望合理的协调多个线程之间的执⾏先后顺序.

在Java多线程编程中,线程间的协调与通信至关重要。wait() 和 notify() 是Object中用于线程协作的核心方法,它们让线程在满足特定条件时等待或被唤醒,从而实现高效的资源利用和任务调度。

二、wait() 方法

1.核心作用

让当前持有该对象锁的线程释放锁并进入等待状态,直到其他线程调用此对象的notify()或notifyAll()方法,或者等待时间超时。

锁的等待,是不受控制的.某个线程的代码执行到加锁的逻辑,一定触发等待吗?不一定!!不确定其他线程是否是"加锁”状态

例子

线程ABCD到ATM机器取钱 A先进入ATM机上锁 此时发现ATM机器已经没钱了 只能等运钞机来放钱进入ATM机 但是A此时不想走也不想给别人抢先等 所以A出来等锁 其它线程不知道啥情况一直死等

当多个线程竞争一把锁的时候,获取到锁的线程如果释放了,其他是哪个线程拿到锁?不确定(随机调度)
操作系统的调度是随机的.其他线程都属于在锁上阻塞等待,是阻塞状态.当前这个释放锁的线程,是就绪状态.这个线程有很大的概率能够再次拿到这个锁

当拿到锁的线程,发现要执行的任务,时机还不成熟的时候,就使用 wait 阻塞等待.

2.使用前提

wait这个等待,最关键的一点,要先释放锁.给其他线程获取锁的机会

案例

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        System.out.println("wait 之前");
        lock.wait();
        System.out.println("wait 之后");
    }
}

没有上锁是会报异常的

先加上锁才能谈释放

要求synchronized的锁对象必须和wait 的对象是同一个

三、如何结束wait等待?

此时wait()释放锁进入阻塞等待状态 如何唤醒?

1.设置wait()时间等待的限制

类试sleep()线程休眠。

2.notify()

随机唤醒一个等待该对象锁的线程

public class Demo {
    public static void main(String[] args) {
        Object locker = new Object();

        Thread t1 = new Thread(() -> {
            try {
                System.out.println("wait 之前");
                synchronized (locker) {
                    locker.wait();
                }
                System.out.println("wait 之后");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread t2 = new Thread(() -> {
            Scanner scanner = new Scanner(System.in);
            System.out.println("输入任意内容 通知唤醒t1");
            scanner.next();

            synchronized (locker){
                locker.notify();
            }
        });
        t1.start();
        t2.start();
    }
}

如果使用锁对象不同会发生什么?

此时线程依旧阻塞等待 并不能成功唤醒

注:务必要确保,先wait,后notify,才有作用如果是先 notify,后 wait,此时wait无法被唤醒.notify 的这个线程,也没有副作用(notify一个没有在wait的对象,不会报错)

3.notifyAll()

一次notify()只能唤醒一个wait() 而notifyAll() 可以一次性把wait()阻塞全部唤醒

public class Demo28 {
    public static void main(String[] args) {
        Object locker = new Object();

        Thread t1 = new Thread(() -> {
            try {
                System.out.println("t1 wait 之前");
                synchronized (locker){
                    locker.wait();
                }
                System.out.println("t1 wait 之后");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                System.out.println("t2 wait 之前");
                synchronized (locker){
                    locker.wait(10000);
                }
                System.out.println("t2 wait 之后");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread t3 = new Thread(() -> {
            Scanner scanner = new Scanner(System.in);
            System.out.println("输入任意内容 唤醒所有线程");
            scanner.next();
            synchronized (locker){
                locker.notifyAll();
            }

        });
        t1.start();
        t2.start();
        t3.start();
    }
}

四、wait() 和 sleep()区别

1.所属类不同:wait() 属Object类 任何对象都可调用wat(), sleep() 只属Thread类.

2.wait()释放锁,而sleep() 持锁不释放。

3.wait()通过notify()/notifyAll()或超时唤醒,sleep()只能通过超时后自动唤醒。

4.wait()必须在synchronized块中使用,而sleep()无要求。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐