【Java】wait和notify方法

wait()和notify()方法都是Object类中的方法。由于每个类都会继承Object类,所以每个对象中都会包含这些方法。
在这里插入图片描述

wait方法

wait() 是让线程等待一段时间,死等。对应到线程的状态就是WAITING。
wait(long) 是让线程等待一段时间,指定的时间到了就不等了,过时不候。对应到线程的状态就是TIMED_WAITING。

wait()和join()的区别

之前介绍过一个join()方法,这个方法也是让线程等待。不同的是:
join()方法是Thread类中的方法。join()是让调用方去等,wait()是让执行方去等
比如我爸妈让我去买包子,他们必须要等我买回来了才能吃,这个过程就是join(),到了包子铺老板的包子还没出锅,相当于我在等待某些资源,相当于notify()。

wait()和sleep()的区别

本质上来说都是让线程阻塞等待,但是两个方法没啥关系。
wait()是Object类中定义的方法,sleep是Thread类中定义的方法。
wait()必须要和synchronized搭配使用,调用之后会释放锁,sleep()只是让线程进入休眠,和锁无关。
在这里插入图片描述

notify()和notifyAll()

notify() 方法是唤醒线程,只唤醒一个线程,并直接参与锁竞争;
notifyAll() 一次性唤醒所有的线程,线程共同去参与锁竞争。
比如去包子铺买包子,大家都在等待。包子做好之后老板指定某一个人来买,相当于notify();没指定人相当于大家都可以买,此时就是notifyAll()。

实例

public class Demo03_Wait_Notify {
    
    
    private static Object locker = new Object();
    public static void main(String[] args) {
    
    
        // 买包子线程
        Thread t1 = new Thread(() -> {
    
    
            while (true) {
    
    
                System.out.println(Thread.currentThread().getName() + " wait 之前");
                try {
    
    
                    // 等待资源,线程会被阻塞
                    locker.wait();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " wait 之后");
                System.out.println("=============================");
            }
        }, "t1");
        // 启动线程
        t1.start();

        // 包子铺老板线程
        Thread t2 = new Thread(() -> {
    
    
            while (true) {
    
    
                System.out.println(Thread.currentThread().getName() + " notify 之前");
                // 唤醒资源
                locker.notify();
                System.out.println(Thread.currentThread().getName() + " notify 之后");
                // 等待一会
                try {
    
    
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "t2");
        // 启动线程
        t2.start();
    }
}

上面的代码在运行时会报下面的异常:非法的监视器状态异常,所以需要将wait()和notify要用synchronized包裹,确保wait和notify是同一个锁对象
在这里插入图片描述

public class Demo03_Wait_Notify {
    
    
    private static Object locker = new Object();
    public static void main(String[] args) {
    
    
        // 买包子线程
        Thread t1 = new Thread(() -> {
    
    
            while (true) {
    
    
                System.out.println(Thread.currentThread().getName() + " wait 之前");
                try {
    
    
                    // 等待资源,线程会被阻塞
                    synchronized (locker) {
    
    
                        locker.wait();
                    }
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " wait 之后");
                System.out.println("=============================");
            }
        }, "t1");
        // 启动线程
        t1.start();

        // 包子铺老板线程
        Thread t2 = new Thread(() -> {
    
    
            while (true) {
    
    
                System.out.println(Thread.currentThread().getName() + " notify 之前");
                // 唤醒时也使用同一个锁对象
                synchronized (locker) {
    
    
                    locker.notify();
                }
                System.out.println(Thread.currentThread().getName() + " notify 之后");
                // 等待一会
                try {
    
    
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }, "t2");
        // 启动线程
        t2.start();
    }
}

在这里插入图片描述
从执行结果可以看出wait()和notify()被调用后,当前线程都会释放锁资源
在这里插入图片描述


继续加油~

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43243800/article/details/130921333
今日推荐