一、Thread.sleep方法
总结:代码块内调用Thread.sleep方法不会释放监视器等锁资源,被其他线程中断后会抛出中断异常。
验证sleep不会释放锁资源代码示例:
如果线程A获取了锁资源,睡眠过程中,线程B也想获取锁资源,但是获取失败。这间接验证了Thread.sleep静态方法睡眠过程中不会释放锁资源。
private static final Lock LOCK = new ReentrantLock();
public static void main(String[] args) {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
LOCK.lock();
try {
System.out.println("线程A开始睡眠");
Thread.sleep(2000);
System.out.println("线程A睡眠结束");
}catch (Exception e) {
e.printStackTrace();
} finally {
LOCK.unlock();
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
LOCK.lock();
try {
System.out.println("线程B开始执行");
} finally {
LOCK.unlock();
}
}
});
threadA.start();
threadB.start();
}
输出:
线程A开始睡眠
线程A睡眠结束
线程B开始执行
验证sleep睡眠过程被中断后抛出中断异常代码示例:
线程在sleep过程中,如果被其他线程中断,会抛出中断异常。threadA睡眠过程中,被main线程中断后,抛出InterruptedException异常。
private static final Lock LOCK = new ReentrantLock();
public static void main(String[] args) {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
LOCK.lock();
try {
System.out.println("线程A开始睡眠");
Thread.sleep(5000);
System.out.println("线程A睡眠结束");
}catch (InterruptedException e) {
e.printStackTrace();
} finally {
LOCK.unlock();
}
}
});
threadA.start();//开启threadA线程
try {
System.out.println("main线程睡眠开始");
Thread.sleep(2000);
System.out.println("main线程睡眠结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
threadA.interrupt();//main线程内中断threaA
}
输出:
main线程睡眠开始
线程A开始睡眠
main线程睡眠结束
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.run(Thread.java:748)
二、Thread.yield方法
总结:yield方法告知cpu调度器,当前线程请求让出自己的cpu使用。线程让出cpu后处于就绪状态。下次cpu调度还可能有限调度到刚刚让出cpu的线程。
和sleep和wait不同的是:sleep方法让出cpu到指定时间,阻塞挂起,但是不释放锁;wait方法让出cpu直到指定时间或被notify,阻塞挂起,同时释放锁资源。而yield方法仅仅是让出cpu,随后进入就绪状态。