Thread 类中有一个静态的sleep方法,当一个执行中的线程调用了Thread的sleep方法后,调用sleep的线程会暂时让出指定时间的执行权,也就是在这期间不参与CPU的调度,但是该线程所拥有的监视器资源,比如锁
还是持有不让出的。
指定的睡眠时间到了后该函数会正常返回,线程就处于就绪状态
,然后参与CPU的调度,获取到CPU资源后就可以继续运行了。
如果在睡眠期间
其他线程调用了该线程的interrupt()
方法中断了该线程,则该线程会在调用sleep方法的地方抛出InterruptedException异常而返回。
下面举一个例子来说明,线程在睡眠时拥有的监视器资源不会被释放:
/**
* @Author Hory
* @Date 2020/10/19
*/
public class SleepTest {
private static final Lock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(new Runnable(){
public void run(){
lock.lock(); // 获取独占锁
try{
System.out.println("child threadA is in sleep");
Thread.sleep(2000);
System.out.println("child threadA is awaked");
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock(); // 释放锁
}
}
});
Thread threadB = new Thread(new Runnable(){
public void run(){
lock.lock(); // 获取独占锁
try{
System.out.println("child threadB is in sleep");
Thread.sleep(2000);
System.out.println("child threadB is awaked");
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock(); // 释放锁
}
}
});
// 启动线程
threadA.start();
threadB.start();
}
}
运行结果:
child threadA is in sleep
child threadA is awaked
child threadB is in sleep
child threadB is awaked
如上代码首先创建了一个独占锁
,然后创建了两个线程,每个线程在内部先获取锁,然后睡眠,睡眠结束后会释放锁。无论执行多少遍上面的代码都是线程A先输出或者线程B先输出,不会出现线程A和线程B交叉输出的情况。
从执行结果来看,这里线程A先获取了锁,那么线程A会先输出一行,然后调用sleep方法让自己睡眠2s,在线程A睡眠的这2s内那个独占锁lock还是线程A自己持有,线程B会一直阻塞直到线程A醒来后执行unlock释放锁。
下面再来看一下,当一个线程处于睡眠状态时,如果另外一个线程中断了它,会不会在调用sleep方法处抛出异常:
/**
* @Author Hory
* @Date 2020/10/19
*/
public class SleepTest1 {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable(){
public void run(){
try{
System.out.println("child thread is in sleep");
Thread.sleep(10000);
System.out.println("child thread is awaked");
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
}
}
});
thread.start();
Thread.sleep(2000); // 主线程睡眠2秒
thread.interrupt(); // 在主线程内调用子线程的interrupt()终端子线程
}
}
运行结果:
child thread is in sleep
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at testThread.SleepTest1$1.run(SleepTest1.java:13)
at java.lang.Thread.run(Thread.java:748)
如上所示,主线程睡眠2秒,让子线程先运行,子线程在睡眠期间,主线程中断了它,所以子线程在调用sleep方法处抛出了InterruptedException
异常。另外需要注意的是,如果在调用Thread.sleep(long millis)
时为millis参数传递了一个负数,则会抛出IllegalArgumentException
异常,如下所示:
Exception in thread "main" java.lang.IllegalArgumentException: timeout value is negative
at java.lang.Thread.sleep(Native Method)
at testThread.SleepTest1.main(SleepTest1.java:24)