sleep
Thread 类中有一个静态的 sleep 方法,当一个执行中的线程调用了 Thread 的 sleep 方法后,调用线程会暂时让出指定时间的执行权,也就是在这期间不参与 CPU 的调度,但是该线程所拥有的监视器资源,比如锁还是持有不让出的。指定的睡眠时间到了后该函数就会正常返回,线程就处于就绪状态,然后参与 CPU 调度,获取到 CPU 资源后就可以继续执行了
线程在睡眠时拥有的监视器资源不会释放。
public class SleepTest {
/**
* 创建一个独占锁
*/
private static final Lock lock = new ReentrantLock();
public static void main(String[] args) {
//创建线程A
Thread threadA = new Thread(new Runnable() {
public void run() {
//获取独占锁
lock.lock();
try {
System.out.println("子线程 A 睡眠中...");
Thread.sleep(1000);
System.out.println("子线程 A 苏醒...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
});
//创建线程 B
Thread threadB = new Thread(new Runnable() {
public void run() {
//获取独占锁
lock.lock();
try {
System.out.println("子线程 B 睡眠中...");
Thread.sleep(1000);
System.out.println("子线程 B 苏醒...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
});
//启动线程
threadA.start();
threadB.start();
}
}
当一个线程处于睡眠状态是,如果另外一个线程中断了它,会在调用 sleep 方法出抛出异常
public class SleepInterruptTest {
public static void main(String[] args) throws InterruptedException {
//创建线程
Thread thread = new Thread(new Runnable() {
public void run() {
try {
System.out.println("子线程睡眠中...");
Thread.sleep(10000);
System.out.println("子线程苏醒...");
} catch (Exception e) {
e.printStackTrace();
}
}
});
//启动线程
thread.start();
//主线程休眠2s
Thread.sleep(2000);
//主线程中断子线程
thread.interrupt();
}
}
另外需要注意的是,如果在调用 Thread.sleep(long millis) 时为 millis 参数传递了一个负数,则会抛出 IllegalArgumentException 异常。
yield
当一个线程调用 yield 方法时,当前线程会让出 CPU 的使用权,然后处于就绪状态,线程调度器会从线程就绪队列里面获取一个线程优先级最高的线程,当然也有可能会调度到刚刚让出 CPU 的那个线程来获取 CPU 的执行权。
public class YieldTest implements Runnable{
YieldTest(){
//创建并启动线程
Thread t = new Thread(this);
t.start();
}
public void run() {
for (int i = 0; i < 5; i++) {
//当 i=0 是让出 CPU 执行权,放弃时间片,并进行下一轮调度
if (i % 5 == 0){
System.out.println(Thread.currentThread() + "yield cpu ...");
//当前线程让出 cpu 执行权,放弃时间片,进行下一轮调度
Thread.yield();
}
}
System.out.println(Thread.currentThread() + "is over...");
}
public static void main(String[] args) {
new YieldTest();
new YieldTest();
new YieldTest();
}
}
sleep与yield的区别
- 当线程调用 sleep 方法时,调用线程会被阻塞挂起指定时间,在这期间线程调度器不会调度该线程。
- 调用 yield 方法时,线程只会让出自己剩余的时间片,并没有被阻塞挂起,而是处于就绪状态,线程调度器下一次调度时就有可能调度到当前线程执行。