【Java】wait和notify方法

  • wait方法
  • wait()和join()的区别
  • wait()和sleep()的区别
  • notify()和notifyAll()
  • 实例

wait()和notify()方法都是Object类中的方法。由于每个类都会继承Object类,所以每个对象中都会包含这些方法。
【Java】wait和notify方法_第1张图片

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()只是让线程进入休眠,和锁无关。
【Java】wait和notify方法_第2张图片

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是同一个锁对象
【Java】wait和notify方法_第3张图片

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();
    }
}

【Java】wait和notify方法_第4张图片
从执行结果可以看出wait()和notify()被调用后,当前线程都会释放锁资源
【Java】wait和notify方法_第5张图片


继续加油~

【Java】wait和notify方法_第6张图片

你可能感兴趣的:(JavaEE初阶,java,jvm,开发语言,javaee)