0%

并发编程

3.7 sleep和yield

sleep

1.调用sleep会让当前线程从Running进入Timed Waiting状态(阻塞)

2.其他线程可以使用interupt方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException

3.睡眠结束后的线程未必会立刻得到执行

4.建议用TimeUnit的sleep代替Thread的sleep来获得更好的可读性

yield

1.调用yield会让当前线程从Running进入Runnable就绪状态,然后调度执行其它线程

2.具体的实现依赖于操作系统的任务调度器

线程优先级

线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它

如果CPU比较忙,那么优先级高的线程会获得更多的时间片,但CPU空闲时,优先级几乎没作用

不使用yield

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Test9 {
public static void main(String[] args) {
Runnable task1 = () -> {
int count = 0;
for (;;) {
System.out.prinln("---->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两者打印次数基本差不多

image-20231103223923885

开启后

image-20231103224121283

开启优先级

image-20231103224359120

案例-防止CPU占用100%

sleep实现

在没有利用CPU进行计算时,不要让while(true)空转浪费CPU,这时可以使用yield或sleep来让出cpu的使用权给其他程序

1
2
3
4
5
6
7
while(true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
  • 可以使用wait或条件变量达到类似的效果
  • 不同的是,后两种都需要加锁,并且需要响应的唤醒操作,一般适用于要进行同步的场景
  • sleep适用于无需锁同步的场景

不使用sleep,将会占满单核虚拟机资源

image-20231103225132518

使用后

image-20231103225214908