为什么80%的码农都做不了架构师?>>>
关于sleep和wait区别解析:
sleep只是释放CPU资源,并不释放资源锁对象,wait是会释放掉资源锁对象。
比如,有个锁对象object,线程1和线程2都会锁住object对象。运行线程1,线程1中使用wait方法,这个时候,线程1就处于卡死状态了,这时候我们运行线程2,线程2中使用sleep。这时候,如果资源锁没有释放,线程2是不会被执行的,因为资源锁被线程1占用,但是wait会释放资源锁,所以现象就是,线程1会执行,并且拿到资源锁。
搞个例子来看下:
public static Object lock = new Object();
//开启一个线程1 new Thread(() -> {//首先搞个锁对象synchronized (lock) {System.out.println("线程1已拿到资源锁对象");try {//注意此处的区别//lock.wait(5000);Thread.sleep(5000);} catch (Exception ex) {ex.printStackTrace();}System.out.println("线程1资源锁准备释放");}}).start();Thread.sleep(10);//开启一个线程2 new Thread(() -> {//首先搞个锁对象synchronized (lock) {System.out.println("线程2已拿到资源锁对象");try {Thread.sleep(1000);} catch (Exception ex) {ex.printStackTrace();}System.out.println("线程2资源锁准备释放");} }).start();
注意线程1中注释的代码,我们先来看下都是sleep情况下的结果,如下图,线程1资源释放后,线程2才能拿到锁继续执行。
接下来我们把线程1中的sleep换成wati方法来看下结果,线程1拿到资源锁后,调用wait会释放资源锁,这时线程2就可以拿到锁的。如果线程1wait到时间后会继续执行。
接下来测试下,wait唤醒后是否会拿到锁后执行,还是不用拿锁执行。调整下代码,线程1中的wait去掉时间设定,改为手工唤醒。线程2中添加唤醒线程1的方法,然后运行程序看下结果。
//开启一个线程1 new Thread(() -> {//首先搞个锁对象synchronized (lock) {System.out.println("线程1已拿到资源锁对象");try {//注意此处的区别lock.wait();//Thread.sleep(5000);} catch (Exception ex) {ex.printStackTrace();}System.out.println("线程1资源锁准备释放");}}).start();Thread.sleep(10);//开启一个线程2 new Thread(() -> {//首先搞个锁对象synchronized (lock) {System.out.println("线程2已拿到资源锁对象");try {Thread.sleep(1000);//测试线程1是否会再次拿到锁对象lock.notify();System.out.println("已唤醒线程1");Thread.sleep(3000);} catch (Exception ex) {ex.printStackTrace();}System.out.println("线程2资源锁准备释放");} }).start();
线程2唤醒线程1后,线程1并没有马上执行,而是等到线程2将资源锁释放后,线程1才开始执行。
让线程睡眠今天发现还有另外一种方式,本质上其实还是Thread.sleep()
TimeUnit.SECONDS.sleep(4);