区分sleep()/wait()/join()/yield()
文章目录
1.sleep()
- sleep()是Thread中的静态native方法。
- sleep()可以在任何情况下调用。Thread.sleep()会暂停当前线程,且不会释放任何锁资源或者monitor。
1.1 举例分析
val obj = Object()
fun main() {
Thread(RunnableA()).start()
Thread(RunnableB()).start()
}
class RunnableA:Runnable{
override fun run() {
synchronized(obj){
println("A is start!")
Thread.sleep(1000)
println("A is end!")
}
}
}
class RunnableB:Runnable{
override fun run() {
synchronized(obj){
println("B is start!")
Thread.sleep(1000)
println("B is end!")
}
}
}
结果:
A is start!
A is end!
B is start!
B is end!
- 因为Thread.sleep()不会释放锁资源,所以RunnableA阻塞时,仍持有obj的monitor。
- RunnableB只能等待RunnableA执行完毕释放了obj的monitor之后,去获得obj的monitor,然后再执行。
1.2 其他
- 如果其他的线程中断了一个sleep的线程,sleep方法会抛出Interrupted Exception。
2.wait()
- wait()是Object中定义的native方法。
- wait()只能在synchronized block中调用,会释放monitor。
2.1 notify()和 notifyAll()
- 当调用wait()方法后,需要通过调用notify()/notifyAll()来唤醒。
2.2 举例分析
val obj = Object()
fun main() {
Thread(RunnableA()).start()
Thread(RunnableB()).start()
}
class RunnableA:Runnable{
override fun run() {
synchronized(obj){
println("A is start!")
obj.wait()
println("A is end!")
}
}
}
class RunnableB:Runnable{
override fun run() {
synchronized(obj){
println("B is start!")
obj.notify()
println("B is end!")
}
}
}
结果:
A is start!
B is start!
B is end!
A is end!
- RunnableA在执行到obj.wait()时会将当前线程挂起,并释放obj的monitor。接下来RunnableB获得到obj的monitor之后开始执行。
- RunnableB在执行到obj.notify()时,会唤醒RunnableA,但是此时RunnableB仍持有obj的monitor。
- 在RunnableB执行完,释放obj的monitor之后,RunnableA获取到obj的monitor,开始执行剩余部分。
- 注意:如果RunnableA不能被唤醒,那么即使obj的monitor无人持有,RunnableA也会一直等待,不会去竞争monitor资源。
3.yield()
- Thread.yield()方法的作用是放弃当前线程获取CPU的执行权,将让其它的线程去获取。
- 结果是不固定的,有可能一个线程刚放弃CPU的执行权,CPU又将执行权分配给该线程了。
4.join()
- Thread.join()方法的作用是等待这个线程结束。
4.1 举例分析
val threadA = Thread(RunnableA())
val threadB = Thread(RunnableB())
fun main() {
threadA.start()
threadB.start()
}
class RunnableA : Runnable {
override fun run() {
println("A is start!")
threadB.join()
println("A is end!")
}
}
class RunnableB : Runnable {
override fun run() {
println("B is start!")
Thread.sleep(2000)
println("B is end!")
}
}
- 结果:
A is start!
B is start!
B is end!
A is end!
- 当RunnableA执行到threadB.join(),会挂起。
- RunnableB执行完毕会去唤醒thradA,然后RunnableA继续执行。