关于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);