Java 多线程:线程优先级

Posted Wecccccccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 多线程:线程优先级相关的知识,希望对你有一定的参考价值。

1 优先级取值范围

Java 线程优先级使用 1 ~ 10 的整数表示:

  • 最低优先级 1:Thread.MIN_PRIORITY

  • 最高优先级 10:Thread.MAX_PRIORITY

  • 普通优先级 5:Thread.NORM_PRIORITY

2 获取线程优先级

public static void main(String[] args) {
    System.out.println(Thread.currentThread().getPriority());
}

运行结果:

3 设置优先级

Java 使用 setPriority 方法设置线程优先级,方法签名

public final void setPriority(int newPriority)

示例:

public static void main(String[] args) {
    Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
    System.out.println(Thread.currentThread().getPriority());
    Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    System.out.println(Thread.currentThread().getPriority());
    Thread.currentThread().setPriority(8);
    System.out.println(Thread.currentThread().getPriority());
}

运行结果:

newPriority 设置范围在 1-10,否则抛出 java.lang.IllegalArgumentException 异常

public static void main(String[] args) {
    Thread.currentThread().setPriority(0);
    System.out.println(Thread.currentThread().getPriority());
}

运行结果:

4 默认线程优先级

Java 默认的线程优先级是父线程的优先级,而非普通优先级Thread.NORM_PRIORITY,因为主线程默认优先级是普通优先级Thread.NORM_PRIORITY,所以如果不主动设置线程优先级,则新创建的线程的优先级就是普通优先级Thread.NORM_PRIORITY

class CustomThread extends Thread {
    @Override
    public void run() {
        System.out.println("父线程优先级:" + this.getPriority());
        Thread t = new Thread(new CustomRunnable());
        System.out.println("子线程优先级:" + t.getPriority());
    }
}

class CustomRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("CustomRunnable : " + i);
        }
    }
}

public static void main(String[] args) {
    Thread t = new CustomThread();
    t.setPriority(3);
    t.start();
}

运行结果:

5 线程调度

高优先级的线程比低优先级的线程有更高的几率得到执行,实际上这和操作系统及虚拟机版本相关,有可能即使设置了线程的优先级也不会产生任何作用。

class CustomThread extends Thread {
    public CustomThread(String name) {
        super(name);
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
        }
    }
}

public static void main(String[] args) {
    Thread t1 = new CustomThread("A");
    Thread t2 = new CustomThread("B");
    t1.setPriority(Thread.MIN_PRIORITY);
    t2.setPriority(Thread.MAX_PRIORITY);
    t1.start();
    t2.start();
}

运行结果:

6 线程组的最大优先级

我们可以设定线程组的最大优先级,当创建属于该线程组的线程时,新线程的优先级不能超过这个最大优先级

  • 系统线程组的最大优先级默认为 Thread.MAX_PRIORITY

  • 创建线程组时最大优先级默认为父线程组(如果未指定父线程组,则其父线程组默认为当前线程所属线程组)的最大优先级

  • 可以通过 setPriority 更改最大优先级,但无法超过父线程组的最大优先级

7 setPriority 注意事项

该方法只能更改本线程组及其子线程组(递归)的最大优先级,但不能影响已经创建的直接或间接属于该线程组的线程的优先级,也就是说,即使目前有一个子线程的优先级比新设定的线程组优先级大,也不会更改该子线程的优先级。只有当试图改变子线程的优先级或者创建新的子线程的时候,线程组的最大优先级才起作用

8 线程优先级的问题

  • Thread.setPriority() 是否起作用和操作系统及虚拟机版本相关

  • 线程优先级对于不同的线程调度器可能有不同的含义,可能并不是你直观的推测。特别地,优先级并不一定是指CPU的分享。在UNIX系统,优先级或多或少可以认为是CPU的分配,但Windows不是这样

  • 线程的优先级通常是全局的和局部的优先级设定的组合。Java的 setPriority() 方法只应用于局部的优先级。换句话说,你不能在整个可能的范围内设定优先级,这通常是一种保护的方式,你大概不希望鼠标指针的线程或者处理音频数据的线程被其它随机的用户线程所抢占

  • 不同的系统有不同的线程优先级的取值范围,但是Java定义了10个级别(1-10)。这样就有可能出现几个线程在一个操作系统里有不同的优先级,在另外一个操作系统里却有相同的优先级,并因此可能有意想不到的行为

  • 操作系统可能(并通常这么做)根据线程的优先级给线程添加一些专有的行为,如 only give a quantum boost if the priority is below X,这里再重复一次,优先级的定义有部分在不同系统间有差别

  • 大多数操作系统的线程调度器实际上执行的是在战略的角度上对线程的优先级做临时操作,例如当一个线程接收到它所等待的一个事件或者 I/O,通常操作系统知道最多,试图手工控制优先级可能只会干扰这个系统

  • 应用程序通常不知道有哪些其它运行的线程,所以对于整个系统来说,变更一个线程的优先级所带来的影响是难于预测的,例如有一个预期为偶尔在后台运行的低优先级的线程几乎没有运行,原因是一个病毒监控程序在一个稍微高一点的优先级(但仍然低于普通的优先级)上运行,并且无法预计你程序的性能,它会根据你的客户使用的防病毒程序不同而不同

以上是关于Java 多线程:线程优先级的主要内容,如果未能解决你的问题,请参考以下文章

漫画 | Java多线程与并发

了解多线程

如何解决java 多线程问题

Java 多线程基础线程优先级和守护线程

Java多线程系列--“基础篇”10之 线程优先级和守护线程

Java学习-075-多线程08:线程优先级 Thread.setPriority(Thread.MAX_PRIORITY)