0%

16.4.4 线程让步yield

16.4.4 线程让步 yield

yield方法是一个和sleep方法有点相似的方法,它也是Thread类提供的一个静态方法,它也可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。 yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,完全可能的情况是:当某个线程调用了yield方法暂停之后,线程调度器又将其调度出来重新执行。

实际上,当某个线程调用了yield方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行的机会。

程序示例

下面程序使用yield方法来让当前正在执行的线程暂停。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class YieldTest extends Thread
{
public YieldTest(String name)
{
super(name);
}
// 定义run方法作为线程执行体
public void run()
{
for (int i = 0; i < 50 ; i++ )
{
System.out.println(getName() + " " + i);
// 当i等于20时,使用yield方法让当前线程让步
if (i == 20)
{
Thread.yield();//代码0
}
}
}
public static void main(String[] args)throws Exception
{
// 启动两条并发线程
YieldTest yt1 = new YieldTest("高级");
// 将ty1线程设置成最高优先级
// yt1.setPriority(Thread.MAX_PRIORITY);//代码1
yt1.start();
YieldTest yt2 = new YieldTest("低级");
// 将yt2线程设置成最低优先级
// yt2.setPriority(Thread.MIN_PRIORITY);//代码2
yt2.start();
}
}

上面程序中的代码0调用yield静态方法让当前正在执行的线程暂停,让系统线程调度器重新调度。由于程序中代码1、代码2处于注释状态。
此时两个线程的优先级完全一样,所以当一个线程使用yield方法后,另一个线程就会开始执行。运行结果如下所示:

1
2
3
4
5
6
7
...
高级 20
低级 15
...
低级 20
高级 24
...

如果将程序中代码1代码2的注释取消,也就是为两个线程分别设置不同的优先级,则程序的运行结果如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
....
高级 20
低级 10
高级 21
...
高级 49
低级 17
低级 18
低级 19
低级 20
低级 21
...
低级 49

线程让步后,由线程调度器选中就绪状态中的一个线程来执行,优先级高的线程被选中的机会比较大,但也只是机会大而已,低优先级的线程依然有可能得到运行。

sleep方法和yield方法的区别

关于sleep方法和yield方法的区别如下:

  • sleep方法暂停当前线程后,会给其他线程执行机会,不会理会其他线程的优先级;但yield方法只会给优先级相同,或优先级更高的线程执行机会。
  • sleep方法会将线程转入阻塞状态,直到经过阻塞时间才会转入就绪状态;而yield不会将线程转入阻塞状态,它只是强制当前线程进入就绪状态。因此完全有可能某个线程调用yield方法暂停之后,立即再次获得处理器资源被执行。
  • sleep方法声明抛出了InterruptedException异常,所以调用sleep方法时要么捕捉该异常,要么显式声明抛出该异常;而yiled方法则没有声明抛出任何异常。
  • sleep方法比yiled方法有更好的可移植性,通常不建议使用yield方法来控制并发线程的执行。

总结

  • yiled方法使得线程进入就绪状态,系统线程调度器重新调度处于就绪状态的一个线程来运行,因为调用yiled方法的线程此时也处于就绪状态,所以该线程可能被线程调度器选中得以再次运行.
  • sleep方法使得线程进入阻塞状态,睡眠时间结束后,再进入就绪状态

原文链接: 16.4.4 线程让步yield