
1. wait,notify,notifyAll
1.1wait原理

1.2用法
1.3notify唤醒
- notify方法只应该被拥有过该对象的monitor的线程调用
- 一旦线程被唤醒,线程便会从“等待线程集合”中被移除。
- 要等刚才执行notify的线程退出被synchronized修饰的代码并释放monitor后才能抢占monitor,抢到之后才能继续执行。
1.4 wait/notify/notifyAll的特点、性质
- 必须先拥有monitor
- notify只能唤醒其中一个
- 属于Object类
- 只会释放持有的调用wait的对象的锁。
1.5 常见面试题
- 手写两个线程交替打印0-100的奇偶数:synchronized或者wait/notify实现。
- 手写生产者消费者模式。
- 为什么wait需要在同步代码块内使用
没有同步:如果线程1在wait之前切换到另一个线程,另一个线程的notify和notifyAll都执行完了,再切回来执行wait,这样就会造成wait无法唤醒,造成永久等待 。
2. sleep
-
作用:让线程只在预期的时间执行,其他时候不占用CPU资源。
-
不释放锁:
-
中断会抛出InterruptedException并清除中断状态。
-
TimeUnit.SECONDS.sleep()更加优雅。会忽略负参,而不是报错;有更多的API可以调用,例如SECONDS而不是只有ms。
-
面试题:
- wait/notify、sleep异同(方法属于那个对象?线程状态怎么切换)
相同
- 阻塞
- 响应中断
不同
- wait/notify在同步方法中使用
- sleep不释放锁
- sleep要指定时间
- 所属类不同
join
作用:因为新的线程加入,所以要等它执行完再执行(主等子)。
用法:main等待thread1执行完毕。(底层调用的是wait方法)
三个线程abc,怎么保证b在a后运行,c在b后运行(join)
-
中断
实际上是主线程阻塞时被中断。
-
在join期间,主线程是什么状态:Waiting
yield
作用:释放线程的时间片,还是Runnable状态。
定位:JVM不保证遵循
yield和sleep区别:是否随时可能再次被调度