youyichannel

志于道,据于德,依于仁,游于艺!

0%

JUC初探-02

线程的优先级

在Java线程中,通过一个整形变量priority来控制优先级,优先级的范围是[1, 10],在线程创建的时候,可以通过Thread#setPriority(int)方法来修改优先级,默认优先级是5,优先级高的线程分配的CPU时间片的数量要多于优先级低的线程。

示例代码:

public class ThreadPriority {

public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + "(" + thread.getPriority() + ")");

MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");

t1.setPriority(1);
t2.setPriority(10);
t1.start();
t2.start();
}
}

class MyThread extends Thread {

public MyThread(String name) {
super(name);
}

@Override
public void run() {
Thread thread = Thread.currentThread();
for (int i = 0; i < 5; i++) {
System.out.println(thread.getName() + "(" + thread.getPriority() + ") - " + i);
}
}
}

输出结果不确定。

setPriority()方法是JVM提供的一个方法,并且能够调用本地方法setPriority0()

为什么上述代码的输出结果不确定,我们已经设置了优先级了啊?

  1. 现在的计算机都是多核的,线程t1、t2会让哪一个CPU执行结果是不确定的
  2. 优先级不代表先后顺序,优先级低的线程也是有可能拿到CPU时间片的,只是CPU时间片的时间比高优先级的线程的时间片时间短 => 优先级针对的是CPU时间片长短问题。
  3. 实际开发中,不必要使用setPriority()方法。现在都是采用一些信号量控制工具(比如sential、hystrix),实现线程资源的合理调度。其次因为实际运行环境比较复杂,setPriority()方法难以控制。

结论:设置线程优先级时,针对频繁阻塞(休眠或者I/O操作)的线程需要设置较高的优先级,而偏重计算的线程需要设置较低的优先级,确保处理器不会被独占。

守护线程

Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这意味着,当一个JVM中不存在非守护线程时,JVM将会退出。

示例代码:

public class ThreadDaemon {

public static void main(String[] args) {
Thread thread = new Thread(new DaemonThread(), "Daemon Thread");
thread.setDaemon(true); // 设置为守护线程
thread.start();
// main线程退出
}

static class DaemonThread implements Runnable {

@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
} finally {
System.out.println("FINISH!");
}
}
}

}

输出结果:不会输出"FINISH!"

finally块不能保证守护线程的最终执行结果。因此在构建Daemon线程时,不能依靠finally块中的内容来确保执行关闭或者清理资源的逻辑。

来看看setDaemon()方法:

/**
* Marks this thread as either a {@linkplain #isDaemon daemon} thread
* or a user thread. The Java Virtual Machine exits when the only
* threads running are all daemon threads.
*
* <p> This method must be invoked before the thread is started.
*/
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}

注释上和代码中都可以看出,必须要在线程执行start()方法之前设置为守护线程,否则会抛出IllegalThreadStateException异常。

资料:https://www.bilibili.com/video/BV1xM411Z7Ka/ 强推 河北王校长