这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
前言
Sleep 可以让当前线程进行休眠,有如下两个方法:
public static void sleep(long millis) throws InterruptedException ,mills 毫秒
public static void sleep(long millis, int nanos) throws InterruptedException ,millis 毫秒, nanos 纳秒如果让线程休眠 3小时15分16秒132毫秒, 使用上述方法则不够优雅,可以使用 TimeUnit 这个枚举类。
需要注意:Sleep方法不会放弃 monitor 锁的所有权,会释放CPU资源。
实例
- sleep()虽然陷入阻塞,但并不会释放锁,会等待时间耗尽,重新执行(起休眠作用)
所以下述代码运行的结果为Thread-0获取到了锁
Thread-0释放了锁
Thread-1获取到了锁
Thread-1释放了锁
public class SleepWait implements Runnable{
public static void main(String[] args) {
SleepWait sleepWait = new SleepWait();
Thread thread1 = new Thread(sleepWait);
Thread thread2 = new Thread(sleepWait);
thread1.start();
thread2.start();
}
@Override
public void run() {
syn();
}
private synchronized void syn() {
System.out.println(Thread.currentThread().getName()+"获取到了锁");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"释放了锁");
}
}
-
Lock方法同样不会使sleep释放资源,与上述同理
@Override public void run() { lock.lock(); System.out.println(Thread.currentThread().getName()+"获取到了锁"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } System.out.println(Thread.currentThread().getName()+"释放了锁"); }- wait()会使线程陷入阻塞,并且释放锁,需要notify()或者notifyAll()唤醒
-
可以用TimeUnit.SECONDS.sleep()取代sleep(),原因:代码更优雅,时间把控更灵活;对于非法参数(小于0),sleep会抛出异常,TimeUnit.SECONDS.sleep()会忽略
-
关于Sleep()的总结
sleep()方法可以让线程进入Waiting状态,并且不占用CPU资源,但是并不会释放锁,直到规定的时间后再执行,休眠期间如果被中断,会抛出异常并清除中断状态。
-
关于sleep()的常见面试问题
wait/notify、sleep的异同(方法属于哪个对象?线程状态如何切换)
-
相同
- 阻塞
- 响应中断
-
不同
-
同步方法:wait/notify()方法需要在同步方法(synchronize)中执行,而sleep不需要
-
释放锁:wait()释放锁;而sleep并不释放锁
-
指定时间:wait()可以不传参,不传默认0(永久阻塞,直至被唤醒);sleep必须指定时间
-
所属类:wait/notify属于Object类,Sleep属于Thread类;因为java中每个对象都有一把称之为monitor监控器的锁 由于每个对象都可以上锁,这就要求在对象头中有一个用来保存锁信息的位置 这个锁是对象级别的,而非线程级别的,wait/notify/notifyAll也都是锁级别的操作, 他们的锁属于对象,所以把他们定义在Object类中最合适,因为Object类是所有对象的父类;
因为如果把wait/notify/notifyAll方法定义在Thread类中,会带来很大的局限性 比如一个线程可能持有多把锁,以便实现相互配合的复杂逻辑,假设此时wait方法定义到Thread类中 如何实现让一个线程持有多把锁呢?又如何明确线程等待的是那把锁呢? 既然我们是让当前线程去等待某个对象的锁,自然应该通过操作对象来实现,而不是操作线程
-
-