如果你知道run( )方法中已经完成了所需的工作,你可以给线程调度机制一个暗示:你的
工作已经做得差不多了,可以让别的线程使用处理器了。这个暗示将通过调用yield( )
方法的形式来作出。(不过这只是一个暗示,没有任何机制保证它将会被采纳。)
我们可以修改前面的例子,在每次循环之后调用 yield()。
//: c13:YieldingThread.java
// Suggesting when to switch threads withyield().
import com.bruceeckel.simpletest.*;
public class YieldingThread extends Thread {
private static Test monitor = new Test();
private int countDown = 5;
private static int threadCount = 0;
public YieldingThread() {
super("" + ++threadCount);
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while(true){
System.out.println(this);
if(--countDown == 0) return;
yield();
}
}
public static void main(String[] args) {
for(inti = 0; i < 5; i++)
newYieldingThread();
monitor.expect(new String[] {
"#1: 5",
"#2: 5",
"#4: 5",
"#5: 5",
"#3: 5",
"#1: 4",
"#2: 4",
"#4: 4",
"#5: 4",
"#3: 4",
"#1: 3",
"#2: 3",
"#4: 3",
"#5: 3",
"#3: 3",
"#1: 2",
"#2: 2",
"#4: 2",
"#5: 2",
"#3: 2",
"#1: 1",
"#2: 1",
"#4: 1",
"#5: 1",
"#3: 1"
},Test.IGNORE_ORDER + Test.WAIT);
}
} ///:~
使用yield()以后,程序的输出显得比较均衡。但要注意的是,如果输出的字符串再长一
点的话,你就会得到与SimpleThread.java大致相同的输出。你可以试一试,逐步改变
toString( )方法,每次输出更长的字符串,以观察效果。因为调度机制是抢占式的,它
能决定在需要的时候中断一个线程并切换到别的线程,所以如果输入/输出(在main()
所在的线程内执行)占用了太多的时间,它将在run( )有机会调用yield( )之前被中断。
一般来说,yield()使用的机会并不多,你要是想对程序做认真的调整的话,就不能依赖
于它。