/**(1)
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor. The scheduler is free to ignore this
* hint.
*(2)
* <p> Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over-utilise a CPU. Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect.
*(3)
* <p> It is rarely appropriate to use this method. It may be useful
* for debugging or testing purposes, where it may help to reproduce
* bugs due to race conditions. It may also be useful when designing
* concurrency control constructs such as the ones in the
* {@link java.util.concurrent.locks} package.
*/
public static native void yield();
(1)当前线程暗示调度器,它愿意让出对CPU的使用。调度器可以忽略这个暗示,也可以做出相应处理。
说明:如果调度器忽略了这个暗示,那么当前线程将会继续执行,不会停止。如果调度器没有忽略,则当前线程会从执行状态转化为就绪状态,然后调度器会从就绪状态的线程中,选择一个出来,让它使用CPU。
(2)yield方法的初衷是为了提高线程之间的相对进度,防止过度使用CPU的。所以yield方法的使用,一定要经过详细的分析和测试,确保yield能达到预期的效果。
说明:也就是说要知道yield方法可能会被忽略。我们要在这个前提下,去正确使用yield。
(3)适合yield方式使用的场景不多。有需要使用到的地方,一个是竞态条件下为了复现bug,使用yield用于调试。另一个是同步控制的设计需要。
下面举个例子,说明一个yield的使用场景(一定是和while()循环搭配使用的):
public static void main(String[] args) throws InterruptedException {
final AtomicInteger ai = new AtomicInteger(1);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (!ai.compareAndSet(2, 3))
Thread.yield();//当ai的值还没有被赋值为2的时候,线程让出CPU使用权
}
});
t.start();
if (ai.compareAndSet(1, 2)) {//将2赋值给ai
t.join();//等待t线程运行完再往下执行,相当于把线程t的代码加进来了
if (!t.isAlive()) {
int a = ai.get();
System.out.println("a = " + a);//a = 3
} else {
System.out.println("t线程还在运行中");//如果t.join()注释掉的话,会打印这句,否则永远不会打印
}
}
}
可以看出来,t 线程想要把ai的值从2更新为3,需要等待主线的把ai的值从1更新为2以后。所以线程 t 在更新ai值失败以后,调用yield方法,让出了cpu的使用权。如果这时候被调度器忽略的,会继续去更新ai的值。这是ai的值可能是2了,也可能不是。如果不是,t线程会继续重复上述步骤,直到成功赋值为3。(和我们预期的是一样的)
觉得有用的老铁们赞一下呗,谢谢!