java.lang.Thread类中有很多的方法,比如start,join,sleep, interrupt等, 今天我们来谈谈yield方法, 这个是一个native方法, 如下:
public static native void yield();
这个方法的作用是出让自己的CPU, 让其他的线程有限执行,下面我们写一个类测试一下:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class TestYield {
public void test() throws InterruptedException {
/**
* 使用cyclicBarrier, 让两个线程同时执行。
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
Thread a = new Thread(new Runnable() {
@Override
public void run() {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
//出让自己的CPU
Thread.yield();
for(int i=0;i<10;i++){
System.out.println("A"+i);
}
}
});
Thread b = new Thread(new Runnable() {
@Override
public void run() {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
for(int i=0;i<30;i++){
System.out.println("B"+i);
}
}
});
a.start();
b.start();
a.join();
b.join();
}
public static void main(String[] args) throws InterruptedException {
TestYield ty = new TestYield();
ty.test();
}
}
结果:
B0
B1
B2
B3
B4
B5
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
B6
B7
B8
B9
B10
B11
B12
B13
B14
B15
B16
B17
B18
B19
B20
B21
B22
B23
B24
B25
B26
B27
B28
B29
Process finished with exit code 0
每次执行的结果都不一样, 但大部分的结果都是B线程成执行完了, A线程还没有执行完, 虽然B线程的工作量更大。当然想上面的这种结果也经常出现。
敲黑板划重点
yield方法的作用就是出让自己当前的CPU,但是出让后,可能系统又将时间片再次分给了这个线程。
有些同学说yield方法与join方法作用相反, 我觉得这种说法真是害人不浅。
这样我们就有个疑问,既然是这结果又可能是A先执行完, 也可能是B线程先执行完。哪yield到底有什么用呢?
/**
* 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.
*
* <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.
*
* <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();
在自行看一下这个方法的javadoc, 最后一段说的很明白了。
基本上你很少能用到这个方法, 这个方法可能对debug或者测试有用,可能可以帮助用来重现bug, 也可能在设计并发控制程序中有用。
网友评论