java多线程yield和sleep区别
yield和sleep在java中区别和相同组要表现在以下方面:
相同点: Thread.yield()和Thread.sleep()均不会释放锁.同为Thread类的静态方法
不同点: sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会,而yield()方法只会给相同优先级或更高优先级的线程以运行的机会。
yield()概述:
根据jdk文档给出的解释是: 此方法对调度程序发出一个暗示,即当前线程愿意产生当前使用的处理器。
直接导致结果: 会让当前正在执行的线程暂停,但它不会阻塞当前线程,只是将当前线程转入就绪状态。yeild()只是让当前线程暂停一下,让系统的线程调度器重新调度一次,完全可能的情况是:当某个线程调用了yield()线程暂停之后,线程调度器又将其调度出来重新执行。当某个线程调用了yield()方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行机会。
简单理解为:线程主动告诉cpu我不想奋斗了,重开吧,但我的财产(锁)请给我保留;
sleep(long millis)概述
根据jdk文档给出的解释是: 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
直接导致结果: 让当前正在执行的线程暂停一段时间,并进入阻塞状态,其它任何优先级的线程都可以得到执行的机会,即使系统中没有其它可执行的线程,处于sleep()的线程也不会执行,sleep()是用来暂停线程的执行。 此时由于当亲线程尚未释放锁,持有相同锁对象的其他线程也只能干等着当前线程sleep结束.
简单理解为: 线程主动告诉cpu:我累了,先休息会,先让其他人奋斗吧,除了我的小弟们.
代码部分:
package yield;
/**
* @author Song
* @date 2022/4/29 13:47
* @Version 1.0
*/
public class MyYield {
public static void main(String[] args) throws InterruptedException {
byte[] bytes = new byte[0];
Thread t1 = new Thread(() -> {
synchronized (bytes) {
System.out.println("t1 running");
System.out.println("t1 yield start");
Thread.yield();
System.out.println("t1 yield start");
}
});
// 虽然 t1 yield了,cup重排运行线程,但t1与t2持有同一把锁,其他竞锁线程只能一起等候
Thread t2 = new Thread(() -> {synchronized (bytes) { System.out.println("t2 running"); }});
// 由于t1 yield了 且t3不需要锁,可以抢t1的执行权,但是能不能抢得到,不一定 多执行几次打印顺序会有差异
Thread t3 = new Thread(() -> {System.out.println("t3 running");});
// 虽然t4进入sleep状态,但不会释放锁,其他竞锁线程只能一起等候
Thread t4 = new Thread(() -> {
synchronized (bytes) {
try {
System.out.println("t4 running");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t4 sleep end");
}
});
// t5同t3 不需要锁可以抢t1的执行权,但是其优先级低于t3 yield之后会优先排给t5执行
Thread t5 = new Thread(() -> {System.out.println("t5 running");});
t1.setPriority(1); t1.start();
t2.start();
t3.setPriority(10);t3.start();
t4.start();
t5.setPriority(1); t5.start();
}
}
此处代码运行结果:
代码分析:
线程t1,t2,t4持相同锁对象,在t1获得锁之后,虽然调用了yield()方法,但并没有释放锁,所以此时t5(优先级更高)获得了执行权(当然也有可能执行权又回到了t1这里),随后t3执行,执行结束后,选取线程的重任只能落在t1,t2,t4手上,此时t1锁尚未释放,所以只能是t1继续执行yield之后的程序,随后释放锁,而此时t4获得锁对象,随后进入sleep状态,此时等待中的线程只有t2,而t2拿不到锁,只能乖乖排在t4之后,等待t4sleep结束,随后t2执行.