# yield 方法的作用

yield 方法的作用是让当前正在运行的线程放弃 CPU 资源,让给其他线程使用。

public class YieldTest {
public static void main(String[] args) {
Thread t = new Thread(()->{
long startTime = System.currentTimeMillis();
int num = 0;
for (int i = 0; i < 1000000; i++) {
num ++;
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + "完成耗时:" + (endTime - startTime) + "毫秒");
},"线程1");
t.start();
}
}

以上的运行结果是: 线程1完成耗时:3毫秒 ,非常的快

接下来看一下加上 yield 方法:

public class YieldTest {
public static void main(String[] args) {
Thread t = new Thread(()->{
long startTime = System.currentTimeMillis();
int num = 0;
for (int i = 0; i < 1000000; i++) {
num ++;
//让当前线程让出CPU的执行权,给其他线程使用
Thread.yield();
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + "完成耗时:" + (endTime - startTime) + "毫秒");
},"线程1");
t.start();
}
}

以上的运行结果是: 线程1完成耗时:375毫秒 ,可以看出加了 yield 方法比不加慢了很多,这个就是因为当前线程让出了 CPU 的执行权给其他线程了。

这个 yield 方法,只是通知 jvm 要放弃 CPU 的执行权,但是什么时候放弃,放弃多久,这个就不确定了

或许某个线程刚刚放弃,立刻马上又获取到了 CPU 执行权,这也是有可能的。

# 优先级

  • 在操作系统中,线程是有优先级的。系统会把 CPU 资源优先 给 优先级高 的线程使用。
  • java 中优先级具有继承性,子类会默认继承父类的优先级。比如线程 A 中启动了一个线程 B,那么线程 B 和线程 A 的优先级是一样的。

# 优先级具体使用

public class PriorityTest {
public static void main(String[] args) {
Runnable r = () -> {
for (int i = 0; i < 500; i++) {
System.out.println("当前线程的名字是:" + Thread.currentThread().getName() + ",我已经运行到了" + i);
}
System.out.println("当前线程是:" + Thread.currentThread().getName() + ",我已经运行完了");
};

Thread A = new Thread(r, "A");
A.setPriority(1);//设置当前线程的优先级
A.start();

Thread B = new Thread(r, "B");
B.setPriority(8);
B.start();
}
}

结果:在没有设置优先级的情况下,线程谁先运行完,他们的概率是差不多的。但是调用了 setPriprity 方法之后,值更大的会优先完成。

CPU 会优先分配给线程优先级高的线程使用,但是线程优先级低的线程也一样有 CPU 的使用权。

线程优先级高并不代表一定是当前线程执行完之后才会运行优先级低的线程。

虽然设置了优先级,但是优先级低的线程还是有可能先执行完的。(只是概率较低)

# 守护线程

JAVA 中有两种线程,一种是用户线程,一种是守护线程。

守护线程一种特殊的线程,他具有陪伴的意义。当系统中不存在用户线程了之后,守护线程也就随之会销毁。

public class GuardTest {
public static void main(String[] args) {
Thread thread = new Thread(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//线程设置为守护线程之后,这个代码就不会执行
System.out.println("我是子线程,我运行完了...");
});
thread.setDaemon(true); //将线程设置为守护线程
thread.start();
System.out.println("我是main线程,我运行完了...");
}
}

上面的运行结果是只输出了 main 线程的。因为子线程被设置为守护线程,等待 2 秒之后发现主线程已经执行完了,这个时候系统中没有用户线程了,所以子线程直接销毁,也就没有执行后面的代码。

典型的守护线程是 jvm 的垃圾回收,如果所有的用户线程都销毁了,那就没有任何东西可以回收,这个时候垃圾回收器就被销毁掉了。