Java中sleep()和wait()的区别

1. sleep()和wait()的区别

1.1 这两个方法来自不同的类分别是Thread和Object

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

1.2 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁)。

sleep不出让系统资源;wait是进入线程等待池等待,让出系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,出来也没用,要等待其他线程调用notify或者notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

1.3 wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)

synchronized(x){ 
    x.notify() 
   //或者wait() 
}

1.4 sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

2. 总结

两者都可以暂停线程的执行。
Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依然保持,当指定的时间到了又会自动恢复运行状态。

3. 笔试题目

3.1 题目

关于sleep()和wait(), 以下描述错误的一项是()
A、sleep是线程类 (Thread) 的方法,wait是Object类的方法
B、sleep不释放对象锁, wait放弃对象锁
C、sleep暂停线程、 但监控状态仍然保持,结束后会自动恢复
D、wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态

3.2 分析

3.2.1 选项A

sleep是Thread类中的方法,而wait、notify、notifyAll都是Object类中的方法。

sleep、wait的使用范围:
sleep: sleep是Thread类中的静态方法。因此无论是在a线程中调用b的sleep方法,还是在b线程中调用a的sleep方法,谁调用谁就sleep。也因此,sleep可以在任何地方使用。
wait、notify、notifyAll 就很惨了,只能在同步控制方法或同步控制块中使用。

3.2.2 选项B 、C

sleep():
使当前执行线程休眠(暂时停止执行),以指定毫秒数加上指定的纳秒数,以系统定时器和调度器的精度和准确性为准。线程不会丢失任何监视器(monitor)的所有权。
因为sleep()并没释放锁,所以仍旧处在同步状态,监控仍旧存在,睡眠时间结束后自动恢复运行。

wait():
当前线程必须拥有该对象的监视器(monitor)。线程释放此监视器(monitor)的所有权,并等待,直到另一个线程通过调用{@code notify}方法或{@code notifyAll}方法通知等待此对象的监视器的线程醒来。然后线程等待,直到它能够重新获得监视器的所有权并恢复执行。
wait()释放掉锁,所以不再处于同步状态。

注:对象锁就是常说的同步锁——synchronized。

3.2.3 选项D

在Java中,每个对象都有两个池,锁(monitor)池和等待池

锁池: 假设线程A已经拥有了某个对象(不是类)的锁,而其他线程也想要调用这个对象的某个synchronized方法或者代码块。由于这些线程在进入对象的synchronized方法或者代码块时,必须要先获得该对象的锁的拥有权,但是该对象的锁正在被线程A拥有,所以这些线程就进入了该对象的锁池。

等待池: 假设线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(原因是wait()必须出现在synchronized锁里面,自然执行wait()方法前就拥有了这个对象的锁,源代码翻译中提到wait()释放监视器所有权,即释放锁),同时线程A进入该对象的等待池中。如果另一个线程调用了该相同对象的notifyAll()方法,那么处于该对象中的所有线程会进入该对象的锁池中,准备争夺锁的拥有权。如果另一个线程调用了该相同对象的notify()方法,那么仅仅只有一个处于该对象的等待池中的线程(随机的某个)进入锁池,准备得到锁的拥有权。

深入理解:
如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。
优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值