Java中wait和notify详解

简介: Java中wait和notify详解

线程的调度是无序的,随机的,但是也是有一定的需求场景,希望能够有序执行,join算是一种控制顺序的方式(功能有限)——》一个线程执行完,才能执行另一个线程!

本文主要讲解的:wait和notify则有一下功能:

wait:就是让某个线程先暂停下来,等一等

notify:就是把该线程唤醒,能够继续执行

wait:发现条件不满足/时间不成熟,就先阻塞等待

notify:其他线程构造了一个成熟的条件,就可以唤醒wait的等待

wait和notify都是Object的方法,只要你是个类对象(不是基本的数据类型)都可以使用wait和notify

Object.wait主要做的三件事:

  1. 解锁(先加锁,才能解锁)
  2. 阻塞等待
  3. 当收到通知的时候,就会唤醒,同时尝试重新获取锁

wait必须写到synchronized代码块里面~

notify也是要放到synchronized中使用的~

public class Main4 {
    public static void main(String[] args) throws InterruptedException {
        Object object=new Object();
        //加锁对象必须和wait的对象是同一个
        synchronized (object){
            object.wait();
        }
    }
}

加锁对象必须和wait的对象是同一个

对于wait和notify而言:值得注意的是:

必须要先执行wait,然后notify,此时才有效果~

如果现在还没有wait,就notify,相当于:一炮打空(没有额外的副作用,但是代码的功能不能正确执行了!),此时wait无法唤醒,代码也不会出现其他异常~!!

我们来看一下下述代码:

public class Main5 {
    public static void main(String[] args) throws InterruptedException{
        Object locker=new Object();
        Thread t1= new Thread(()->{
            while (true){
                    try {
                        System.out.println("wait 开始");
                        synchronized (locker) {
                            locker.wait();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        });
        t1.start();
//让t1先启动,主线程休息1秒,在主线程休息1秒的过程中,
// t1线程应该执行到:synchronized (locker) {locker.wait(); }的位置,等1秒钟数据到t2开始执行notify
        Thread.sleep(1000);
        Thread t2=new Thread(()->{
            synchronized (locker){
                System.out.println("notify 开始");
                locker.notify();
                System.out.println("notify 结束");
            }
        });
        t2.start();
    }
}

上述代码的运行结果为:

解析:t1先执行,执行到了wait就阻塞了,t1之后t2开始执行,执行到了notify就会通知t1线程开始唤醒(注意:notify是在synchronized内部,就需要t2释放了锁,t1才能继续往下走~

在上述代码中,虽然是t1先执行的,但是可以通过wait,notify控制,让t2先执行一些逻辑,t2执行完之后,notify唤醒t1,t1在继续往下执行~

使用wait阻塞等待会让线程进入WAITING状态

wait也提供了一个带参数的版本,参数指定的是最大等待时间!

不带参数的wait是死等,带参数的wait就会等到最大时间之后,还没人通知,就自己唤醒自己!!

join只能是让t2线程执行完,再继续执行t1,一定是串行的

wait和notify可以让t2线程执行完,再让t1执行……,t1执行完一部分,再让t2执行,t2在执行一部分,在让t1执行…………

对于唤醒操作,还有一个notifyAll(notify用的比较多)

可以有多个线程,等待同一个对象的情况!!如:在t1,t2,t3中都调用了object.wait,此时在main中,调用了object.notify,会随机唤醒t1,t2中的一个线程,另外两个仍然是WAITING状态!如果调用了object.notifyAll,此时就会把t1,t2,t3的三个线程都唤醒,此时三个线程就会重新竞争锁,然后依次执行……

wait和sleep的对比(面试题)

由于wait有一个带参数的版本,用来体现超时时间,这个感觉跟sleep差不多!!

wait也能提前唤醒,sleep也能提前唤醒,

wait解决的是线程之间的顺序控制,sleep单纯的是让当前线程休眠一会!

唯一相同点是:都可以让线程放弃执行一段时间!

wait需要搭配synchronized使用,sleep不需要

wait是Object的方法,sleep是Thread的静态方法~

相关文章
|
2月前
|
Java 程序员
从菜鸟到大神:JAVA多线程通信的wait()、notify()、notifyAll()之旅
【6月更文挑战第21天】Java多线程核心在于wait(), notify(), notifyAll(),它们用于线程间通信与同步,确保数据一致性。wait()让线程释放锁并等待,notify()唤醒一个等待线程,notifyAll()唤醒所有线程。这些方法在解决生产者-消费者问题等场景中扮演关键角色,是程序员从新手到专家进阶的必经之路。通过学习和实践,每个程序员都能在多线程编程的挑战中成长。
36 6
|
2月前
|
安全 Java
JAVA多线程通信新解:wait()、notify()、notifyAll()的实用技巧
【6月更文挑战第20天】Java多线程中,`wait()`, `notify()`和`notifyAll()`用于线程通信。在生产者-消费者模型示例中,它们确保线程同步。`synchronized`保证安全,`wait()`在循环内防止虚假唤醒,`notifyAll()`避免唤醒单一线程问题。关键技巧包括:循环内调用`wait()`,优先使用`notifyAll()`以保证可靠性,以及确保线程安全和正确处理`InterruptedException`。
32 0
|
2月前
|
安全 Java
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
【6月更文挑战第20天】JAVA多线程中,wait(), notify(), notifyAll()是Object类的关键同步机制。wait()让线程等待并释放锁,直到被notify()或notifyAll()唤醒或超时。它们必须在同步块中使用,持有锁的线程调用。notify()唤醒一个等待线程,notifyAll()唤醒所有。最佳实践包括:与synchronized结合,循环检查条件,避免循环内notify(),通常优先使用notifyAll()。
23 0
|
5天前
|
存储 安全 Java
一天十道Java面试题----第二天(HashMap和hashTable的区别--------》sleep、wait、join)
这篇文章是关于Java面试的第二天笔记,涵盖了HashMap与HashTable的区别、ConcurrentHashMap的实现原理、IOC容器的实现方法、字节码的概念和作用、Java类加载器的类型、双亲委派模型、Java异常体系、GC如何判断对象可回收、线程的生命周期及状态,以及sleep、wait、join、yield的区别等十道面试题。
一天十道Java面试题----第二天(HashMap和hashTable的区别--------》sleep、wait、join)
|
8天前
|
Java
Java中notify 和 notifyAll有什么区别
【8月更文挑战第10天】Java中notify 和 notifyAll有什么区别
15 0
|
1月前
|
存储 SQL 安全
Java共享问题 、synchronized 线程安全分析、Monitor、wait/notify以及锁分类
Java共享问题 、synchronized 线程安全分析、Monitor、wait/notify以及锁分类
28 0
|
1月前
|
Java
Java中的线程通信:wait、notify与Condition详解
Java中的线程通信:wait、notify与Condition详解
|
2月前
|
Java
当JAVA多线程遇上wait()和notify():一场奇妙的邂逅
【6月更文挑战第20天】JAVA多线程中,wait()和notify()是线程通信的关键。wait()让线程释放锁进入等待,直到被notify()或notifyAll()唤醒。它们用于协调如生产者-消费者问题中的线程协作,确保在同步块内调用,并伴随条件检查以防止虚假唤醒。示例代码展示了一个简单的共享队列,其中生产和消费使用wait/notify实现同步。
18 0
|
算法 Java Linux
每日一面 - java里的wait()和sleep()的区别有哪些?
每日一面 - java里的wait()和sleep()的区别有哪些?
每日一面 - java里的wait()和sleep()的区别有哪些?
|
Java 调度
java中wait和sleep的区别
java中wait和sleep的区别