7. sleep、yield线程优先级
大约 3 分钟
1、sleep 与 yield
sleep
- 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
- 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出
InterruptedException
- 睡眠结束后的线程未必会立刻得到执行
- 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性(TimeUnit.SECONDS.sleep(1);)
调用sleep
public static void main(String[] args) {
Thread t1 = new Thread("t1") {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.start();
log.debug("t1 state: {}", t1.getState());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("t1 state: {}", t1.getState());
}
输出
22:23:02.365 c.Test6 [main] - t1 state: RUNNABLE
22:23:02.893 c.Test6 [main] - t1 state: TIMED_WAITING
调用interrupt
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread("t1") {
@Override
public void run() {
log.debug("enter sleep...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
log.debug("wake up...");
e.printStackTrace();
}
}
};
t1.start();
Thread.sleep(1000);
log.debug("interrupt...");
t1.interrupt();
}
输出
22:26:48.155 c.Test7 [t1] - enter sleep...
22:26:49.158 c.Test7 [main] - interrupt...
22:26:49.158 c.Test7 [t1] - wake up...
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at cn.itcast.test.Test7$1.run(Test7.java:14)
yield
- 调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程,注意:如果没有其他线程的话,可能还是执行当前线程
- 具体的实现依赖于操作系统的任务调度器
2、sleep yield区别
共同点:
1.都是Thread类中的类方法
2.都会导致正在执行的线程释放CPU
区别:
1.线程进入的状态不同:sleep方法导致线程进入到阻塞状态,yield方法导致线程进入就绪状态
2.是否考虑线程优先级:sleep方法不会考虑线程优先级,当一个线程调用sleep方法释放CPU后,所有优先级级别的线程都有机会获得CPU。yield方法会考虑线程优先级。当一个线程调用sleep方法释放CPU后,与该线程具有同等优先级,或优先级比该线程高的线程有机会获得CPU
3.可移植性:sleep方法比yield方法具有更好的可移植性
4.是否抛出异常:sleep方法声明抛出InterruptedException,而yield方法没有声明任何异常
5.是否有参数:sleep方法在Thread类中有两种重载形式,sleep(long ms),sleep(long ms,int nanos)yield方法没有参数
3、线程优先级
- 线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它
- 如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用
所以不一定优先级设置高就一定能有限执行,具体执行依赖任务调度器。
Runnable task1 = () -> {
int count = 0;
for (;;) {
System.out.println("---->1 " + count++);
}
};
Runnable task2 = () -> {
int count = 0;
for (;;) {
// Thread.yield();
System.out.println(" ---->2 " + count++);
}
};
Thread t1 = new Thread(task1, "t1");
Thread t2 = new Thread(task2, "t2");
// t1.setPriority(Thread.MIN_PRIORITY);
// t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
这里读者可将注释去掉自行实践,即可体会yield与优先级的使用。
本文来自博客园,作者:|旧市拾荒|,原文:https://www.cnblogs.com/xiaoyh/p/16651175.html