方法Thread.yield
:
使当前正在执行的线程对象暂时暂停和 允许其他线程执行。
所以在下面的代码中:
public class Test implements Runnable {
private int stopValue;
public Fib(int stopValue){
this.stopValue = stopValue;
}
@Override
public void run() {
System.out.println("In test thread");
for(int i = 0; i < stopValue; i++){
c = i + 1;
}
System.out.println("Result = "+c);
}
public static void main(String[] args){
int defaultStop = 1024;
if(args.length > 0){
defaultStop = Integer.parseInt(args[0]);
}
Thread a = new Thread(new Fib(defaultStop));
System.out.println("In main");
a.setDaemon(true);
a.start();
Thread.yield();
System.out.println("Back in main");
}
}
我希望我能看到:
In main
然后In test thread
其余的将是未定义的。但我不明白为什么有时候我只会看到:
In main
和Back in main
而不是来自Test
帖子的任何打印声明?
答案 0 :(得分:4)
yield()是对已安排的操作系统的提示,但在调度方面没有提供任何保证。它并不总是停留很长时间。如果你重复调用它可能只需要几微秒。
启动一个线程需要时间,即使主线程暂停,也可能在后台线程启动之前完成。
如您所见,yield()暂停非常短暂。
long start = System.nanoTime();
long runs = 20000000;
for (int i = 0; i < runs; i++)
Thread.yield();
long time = System.nanoTime() - start;
System.out.printf("Thread.yield() took an average of %,d ns.%n", time / runs);
打印
Thread.yield() took an average of 148 ns.
相比之下,System.nanoTime在我的机器上花费的时间更长。
long start = System.nanoTime();
long runs = 20000000;
for (int i = 0; i < runs; i++)
System.nanoTime();
long time = System.nanoTime() - start;
System.out.printf("System.nanoTime() took an average of %,d ns.%n", time / runs);
打印
System.nanoTime() took an average of 656 ns.
两次都会因操作系统和操作系统以及机器而异。
答案 1 :(得分:2)
好吧,yield()可能什么都不做,因为就绪线程集小于核心数,在这种情况下两个线程都可以运行,而main()将继续运行到核心它在操作系统发出问题时(很可能是队列),调用其核心间驱动程序在另一个CPU核心上运行新线程。然后是与'System.out.println'的交互 - 一个可能用互斥锁保护的输出流调用。
我无法快速找到关于yield()在不同环境/ CPU / OS中实际做什么的任何可理解的解释 - 这是我从未使用过的原因之一。另一个是,无论它如何运作,我都无法想到它的任何用途。
答案 2 :(得分:0)
在线程有机会启动之前,主进程可能已经退出。无法保证Thread.yield()
将强制线程在任何特定时间运行。如果线程没有启动,则setDaemon()
将无效。
答案 3 :(得分:0)
尝试使用:
替换Thread.yield()try {
Thread.sleep(500);
} catch (InterruptedException ex) {
System.out.println(ex);
}
答案 4 :(得分:0)
@ Peter的答案很好,但我想补充一些额外的信息作为答案。
首先,如其他地方所述,a.setDaemon(true)
导致JVM 不等待Thread a
完成后退出。如果您真正的问题是如何确保Thread a
在之前关闭setDaemon(true)
可能是解决方案。当JVM退出时,可以杀死守护程序线程。将等待非守护程序线程。因此,main()
方法可能会返回,主线程可能会退出,但您的Thread a
仍会运行完毕。
就Thread.yield()
而言,如你所说,javadocs状态:
然而,这有点误导。例如,如果您的架构上有2个线程正在运行且处理器上有2个或更多处理器,则使当前正在执行的线程对象暂时暂停并允许其他线程执行。
yield()
实际上将成为无操作。运行队列中没有其他线程正在等待处理器资源,因此主线程将被快速重新安排,并将以最小的暂停继续运行。
即使您在单个CPU系统上运行且Main
执行yield()
,您的Thread a
也会执行System.out
即IO。 IO可能会阻止导致线程执行立即切换回Main
。
当涉及到它时,只有在非常独特的情况下才需要使用yield()
。我已经完成了多线程编程的很多,我从来没有使用它。相信JVM线程调度将在时间切片方面做“正确的事”,除非你有相反的探查器输出或专家建议,否则总是建议。