首先明确一点,在一个线程拿到锁的时候,其他线程向拿到锁就必须要等待。
/**
* @author FanQie
* @date 2022/7/30 10:43
*/
public class SleepYield {
private static Object resource = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (resource) {
System.out.println(Thread.currentThread().getName() + " is running...");
}
});
Thread thread2 = new Thread(() -> {
synchronized (resource) {
System.out.println(Thread.currentThread().getName() + " is running...");
thread1.yield();
System.out.println(Thread.currentThread().getName() + " have finished.");
}
});
thread1.start();
thread2.start();
}
}
如上代码所示,以yield()为例。
- 假设yield()为非静态方法,若thread2拿到锁,调用了thread1的yield()方法,意为让thread1暂时放弃当前占有的CPU时间片,与大家一起再进行时间片竞争。关键是thread1现在处于阻塞状态!它在等待thread2释放锁,它根本没有占用CPU时间片。所以此时调用thread1的yield()方法是没有意义的!
- sleep()方法道理类似,本来就是阻塞状态,所以没必要再阻塞,即使“自然阻塞状态”比如是10ms,你设置了100ms,而“自然阻塞状态”持续时间是无法预测的,所以设定的休眠时间便失去了意义!
- 而对于单线程而言,即使没有锁的争夺,在一个线程执行的时候另外一个线程也处于“不占有CPU时间片的状态”,什么时候再拿到时间片或者多长时间竞争一次CPU时间片都是无法预测的。所以在正在执行的线程里调用另外一个线程的yield()和sleep()方法依然是没有意义的。
ps:有人可能会问怎么没有列举线程调用自己的实例方法来yield或者sleep的情况呢?
答:调用自己的实例方法跟调用类方法效果是一样的,所以不用考虑这种情况。
在网上搜了一下,大多都说“Thread 类的 sleep()和 yield()方法将在当前正在执行的线程上运行。所以在其他处于等待状态的线程上调用这些方法是没有意义的。这就是为什么这些方法是静态的。”还都出奇的一致,一个字不差!看完之后一脸懵,哪跟哪啊这是,特别怀疑大家都说抄的同一个人的,而自己也不怎么明白。现在想想,这些话说的很对,只不过中间差了一些解释说明,不是初级玩家能看懂的。
以上都是个人见解,欢迎大家批评指正!