0x0 前言
在多线程中,sleep和wait 是两个容易混淆的功能,看上去都是实现等待的功能,但实际上又有一些区别。此文意在探讨他们之间最本质的区别——对线程锁的影响。
0x1 区别
0x1_1 sleep()
sleep()
使当前线程进入停滞状态(阻塞当前线程),让出CUP的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会;
sleep()
是Thread类的Static(静态)的方法;因此他不能改变对象的机锁,所以当在一个Synchronized块中调用Sleep()
方法是,线程虽然休眠了,但是对象的机锁并木有被释放,其他线程无法访问这个对象(即使睡着也持有对象锁)。
在sleep()
休眠时间期满后,该线程不一定会立即执行,这是因为其它线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。
0x1_2 wait()
wait()
方法是Object类里的方法;当一个线程执行到wait()
方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁(暂时失去机锁,wait(long timeout)
超时时间到后还需要返还对象锁);其他线程可以访问;
wait()
使用notify
或者notifyAlll
或者指定睡眠时间来唤醒当前等待池中的线程。
wiat()
必须放在synchronized block
中,否则会在program runtime时扔出java.lang.IllegalMonitorStateException
异常。
0x1_3 总结
总的来说,sleep()
和wait()
最大的区别就是sleep会继续持有锁,而wait
则会释放锁
\ | sleep() | wait() |
---|---|---|
锁 | 不释放 | 释放 |
所属类 | Thread.class | Object.class |
指定时间 | 可以(必须) | 可以(不必须) |
被唤醒 | 不可以 | 可以(notify ) |
0x2 代码示例
如下代码,反别使用sleep
和wait
来看执行结果:
public class SleepThread implements Runnable {
int number = 10;
public void firstMethod() throws Exception {
synchronized (this) {
System.out.println("first thread-" + Thread.currentThread().getName());
/*
* sleep 不会释放锁,依然持有锁
* wait 会释放锁,让出资源
*/
// Thread.sleep(2000);
this.wait(2000);
number += 100;
System.out.println("first:" + number);
}
}
public void secondMethod() throws Exception {
synchronized (this) {
System.out.println("second thread-" + Thread.currentThread().getName());
number *= 200;
}
}
public void run() {
try {
firstMethod();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SleepThread threadTest = new SleepThread();
Thread thread = new Thread(threadTest);
thread.start();
try {
//确保先执行线程中的代码
Thread.sleep(500);
threadTest.secondMethod();
} catch (Exception e) {
e.printStackTrace();
}
}
}
sleep() 结果
first thread-Thread-0
first:110
second thread-main
wait()结果
first thread-Thread-0
second thread-main
first:2100
0x3 参考文献
0x4 关于我
- @Author:Zemo
- @Email:zemochen#126.com
- 欢迎转载,让更多的人学到东西