多线程中wait()、sleep()、notify()和notifyAll()方法异同点【面试】

现在面试基本上都会被问及到多线程,就有很高概率问到wait() 和 sleep() 这两者的区别1、wait()、sleep() 方法相同点(1)都是对线程的操作;(2)都需要抛异常; (这一点我遇到很多人答错,记住这两者都会抛异常)(3)都会让当前运行线程进入阻塞状态。2、wait()、sleep() 方法不同点(1)使用位置不同: wait() 方法必须在同步代码中,sleep() 则不需要;(2)申明位置不同: wait() 方法是 Object类 中的方法,sleep() 方法是 T.
摘要由CSDN通过智能技术生成


现在面试基本上都会被问及到多线程,就有很高概率问到wait()sleep() 这两者的区别

1、wait()、sleep() 方法相同点

(1)都是对线程的操作;

(2)都需要抛异常 (这一点我遇到很多人答错,记住这两者都会抛异常)

(3)都会让当前运行线程进入阻塞状态

(4)都能在阻塞过程中感受到中断信号

2、wait()、sleep() 方法不同点

(1)使用位置不同: wait() 方法必须在synchronized 同步代码中,sleep() 则不需要;

(2)申明位置不同: wait() 方法是 Object类 中的方法,sleep() 方法是 Thread类中的静态方法

(3)调用时是否释放锁不同:wait() 调用时线程是要释放同步监视器(锁)的,sleep() 不会释放同步监视器(锁);

(4)wait() 方法要结合 notify() 方法或者 notifyAll() 方法一起使用,不然就会一直阻塞线程。(没有设置时间的情况下)

(5)sleep() 方法是必须要求指定一个时间,超时之后就会恢复操作,而 wait() 方法如果没有设置时间的话,会一直处于等待状态,只有等到被唤醒或者被中断才会恢复。

重点说明一下:

1、wait() 是和 synchronized 锁一起使用,而 await() 是和 Lock 锁一起使用,await() 方法是 Condition 接口中的方法;

2、wait() 为什么必须在 synchronized 同步代码中使用呢 ?

  • 主要原因是为了程序的安全性,必须保证每一个线程持有锁之后的操作都是原子的,不然可能会带来线程之间的通信失败。比如说本来现在是应该阻塞当前线程,由于不是原子的,这时候要是没有阻塞这个线程,那么此时要是执行到要去唤醒刚刚没有被阻塞的那个线程就是不对的。

  • 另外 wait() 方法是会释放锁的,要是不是原子的,第一个线程还没有执行到 wait() 方法,也就是还没有释放当前锁,此时另外一个线程就开始执行显然是不会持有锁的,那么会报IllegalMonitorStateException异常的。

  • java.lang.Object 类定义了wait(),notify(),notifyAll)方法,这些方法的具体实现,依赖于一个叫 ObjectMonitor模式 实现的。

在这里插入图片描述
      这里其实就涉及到了 synchronized 的锁膨胀机制和对象头中 MarkWord 的知识了(两篇文章都是我的浅显理解)

3、为什么会把 wait() 方法定义在 Object类中,sleep() 方法定义在 Thread类中 ?(我的理解是:)

  • 我们都知道,Object 类是所有类或对象的父类,另外加锁其实就是给对象加锁,那么 wait()、notify()、notifyAll()定义在 Object 这个对象父类中就是理所当然的了,而不是 Thread 线程类中;
  • 如果把wait() 、notify()、notifyAll() 方法定义在 Thread 类中,我们就不好让一个线程持有对象锁(非同一时刻),又不好确定线程等待的是哪一把锁?既然是线程等待某一个对象的锁,那么操作对象是最为合适的,而不是线程;
  • 另外:每一个对象的对象头 markword 里都会有锁状态信息,也就是用此来表示对象的锁状态,是无锁、偏向锁、轻量级锁、重量级锁呢?而不是在每一个线程里。想了解对象的对象头 markword 或者 synchronized 的锁膨胀机制可以看这里

3、notify() 方法和 notifyAll() 方法

(1)notify() 方法和 notifyAll() 方法是Object类中定义的方法;

(2)notify() 方法:

       ①线程不能一直在等待集合中,必须有方法对其进行唤醒,notify() 方法可以对线程进行唤醒;

       ②使用 this 作为当前对象的引用,故可以直接写成 notify() 进行调用,而不必用当前对象点上 notify() 方法;(这一点下面Demo中 有演示)

       ③当使用某个对象的 notify() 方法时,将从该对象的等待集合中任意选择一个等待的线程唤醒,唤醒的线程将从等待集合中删除

(3)notifyAll()方法:

      ①notifyAll() 方法会将所有在等待集合中的线程唤醒

      ②由于所有的被唤醒的线程仍然要去争用synchronized锁,而synchronized锁具有排他性,最终只有一个线程获得该锁,进行执行状态,其他线程仍要继续等待,只是现在被唤醒的这些线程都有去抢夺同步监视器(锁)的权利了。

4、wait() 方法 sleep() 方法使用及抛异常

      wait() 方法演示:

public synchronized void productProduct() {
   
        if (productCount < 20) {
   //店员有20个产品就停止生产产品
            productCount++;
            notify();//唤醒阻塞的一个线程
            System.out.println(Thread.currentThread().getName
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值