(一)java线程优先级

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

获得线程优先级方法为:getPriority()

设置线程优先级方法为:setPriority(int x)

线程的优先级用数字来表示,范围1~10。jdk中提供了常量类可方便设置

-   **Thread.MIN_PRIORITY = 1; 最小优先级**
-   **Thread.MAX_PRIORITY = 10; 最大优先级**
-   **Thread.NORM_PRIORITY = 5; 默认优先级(main方法)**

以下为测试代码,看java代码实际运行中的优先级效果。 代码表述为:分别创建两个线程,为两个线程设置优先级为1和10,同时开启线程,并同时打印当前线程名和线程优先级。

public class ThreadPrority {
    public static void main(String[] args) throws JsonProcessingException {
        System.out.println(Thread.currentThread().getName()
                +"("+Thread.currentThread().getPriority()+ ")");

        Thread t1=new MyThread("t1");    // 新建t1
        Thread t2=new MyThread("t2");    // 新建t2
        t1.setPriority(1);                // 设置t1的优先级为1
        t2.setPriority(10);                // 设置t2的优先级为10
        t1.start();                        // 启动t1
        t2.start();                        // 启动t2
    }
}
class MyThread extends Thread{
    public MyThread(String name) {
        super(name);
    }
    @SneakyThrows
    public void run(){
        for (int i=0; i<5; i++) {
            System.out.println(Thread.currentThread().getName()
                    +"("+Thread.currentThread().getPriority()+ ")"
                    +", loop "+i);
        }
//        Thread.sleep(100000);
    }
};

执行多次效果为:

java 优先级 进程 java设置优先级_优先级

java 优先级 进程 java设置优先级_jvm_02

为什么会导致这样呢,我们接下来来看一下setPriority的源码:

public final void setPriority(int newPriority) {
    ThreadGroup g;
    checkAccess();//这里是判断当前线程是有权限
    if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {//大于10或者小于1参数输入有误
        throw new IllegalArgumentException();
    }
    //这里g是获得当前线程组,此时t1、t2的线程组都是main线程,这俩线程都是基于main线程创建出来的
    if((g = getThreadGroup()) != null) {
        if (newPriority > g.getMaxPriority()) {
        //这里的意思是如果当前设置线程比线程组的最大线程优先级还要大,就设置成线程组的线程优先级
            newPriority = g.getMaxPriority();
        }
        //native 操作系统设置优先级
        setPriority0(priority = newPriority);
    }
}

我们先在t1设置优先级时打个断点,debug如下:

java 优先级 进程 java设置优先级_java 优先级 进程_03

 

setPriority 这个方法,他是 jvm 提供的一个方法,并且能够调用 本地方法 setPriority0. 我们发现优先级貌似没有起作用,为什么?

  1. 我们现在的计算机都是多核的,t1,t2 会让哪个cpu处理不好说。由不同的cpu同时提供资源执行。
  2. 优先级不代表先后顺序。哪怕你的优先级低,也是有可能先拿到我们的cpu时间片的,只不过这个时间片比高优先级的线程的时间片短(或者说是概率低)。 优先级针对的是 cpu时间片的长短问题。
  3. 目前工作中,实际项目里,不必要使用setPriority方法。我们现在都是用 hystrix, sential也好,一些开源的信号量控制工具,都能够实现线程资源的合理调度。这个 setPriority方法,很难控制。实际的运行环境太复杂。

但是需要注意:

默认情况下,一个线程会继承构造它的那个线程的优先级。(前面例子中的t1、t2都继承了main线程默认的5优先级,但是后来又重新设置了新的优先级)

每当线程调度器有机会选择新线程时,它首先选择具有较高优先级的线程。但是,线程的优先级高度依赖于系统。当虚拟机依赖于宿主机平台的线程实现时,Java线程的优先级会映射到宿主平台的优先级,平台的线程优先级别可能比Java的10个级别多,也可能更少。
例如,Windows有7个优先级别。Java的一些优先级会映射到同一个操作系统优先级。在Oracle为Linux提供的Java虚拟机中,会完全忽略线程优先级————所有线程都具有相同的优先级。

在没有使用操作系统线程的Java早期版本中,线程优先级可能很有用。不过现在不要使用线程优先级了

(二)java守护线程

Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这意味着,当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出。可以通过调用Thread.setDaemon(true)将线程设置为Daemon线程。 代码演示如下:

java 优先级 进程 java设置优先级_jvm_04

 

我们可以看到,此时守护线程并没有执行整个程序就已经结束了,尤其是finally都没有执行,说明当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出

其中setDaemon()源码如下:

public final void setDaemon(boolean on) {
    checkAccess();
    if (isAlive()) {//如果当前线程是存活的则报错
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

isAlive(): 必须要先设置线程是否为守护线程,然后再调用start方法。如果你先调用start。