zoukankan      html  css  js  c++  java
  • Java 多线程(二)之 Thread 优先级

    @

    Thread 中线程优先级相关属性

    每个线程均有优先级,在 Thread 中, 与优先级对应的属性如下:

    /**
     * 线程的优先级属性
     */
    private int priority;
    /**
     * 线程所能拥有的最大优先级.
     */
    public final static int MIN_PRIORITY = 1;
    
    /**
     * 线程默认的优先级.
     */
    public final static int NORM_PRIORITY = 5;
    
    /**
     * 线程所能拥有的最大优先级.
     */
    public final static int MAX_PRIORITY = 10;
    

    相关函数

    在此只讨论 Thread 类中的。

    优先级初始化

     private void init(ThreadGroup g, Runnable target, String name,
                          long stackSize, AccessControlContext acc) {
        // ....
        this.priority = parent.getPriority();
        setPriority(priority);
       // ....
    }
    

    init() 函数对优先级进行了初始化。并调用 setPriority(priority) 函数进行设置。从中得知, 线程的优先级是继承于创建它的线程的。

    设置优先级

    在 init() 中, 除了给 this.priority 赋值, 还调用了 setPriority(priority) 函数, 因为在该函数内部还调用了一个 native 方法。

    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        // 不能大于最大优先级 MAX_PRIORITY
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            // 如比所属线程组的最大优先级还大, 则取线程组的最大优先级
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
    

    由代码可知, 设置的优先级不能大于最大优先级,也不能大于所在线程组的最高优先级

    获取优先级

    获取当前的优先级, 其实就是返回 priority 属性的值。

    public final int getPriority() {
        return priority;
    }
    

    从以上可知, 在 Thread 中, 线程的优先级有如下特点:

    1. Java 线程的优先级从 1~10;
    2. Java 线程默认优先级是 5;
    3. Java 线程的优先级继承于创建它的线程。

    是不是感觉 2 和 3 有所矛盾呢?可以在后面的代码和结果中找答案。

    默认优先级

    先上代码来感受一下线程优先级的作用:

    public class ThreadPriorityTest {
        class PrimeRun implements Runnable {
            public void run() {
                System.out.println(Thread.currentThread().getName() +"::"+
                        Thread.currentThread().getPriority());
                System.out.println(Thread.currentThread().getName() + " Run begin");
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()+"::"+i);
                }
                System.out.println(Thread.currentThread().getName() + " Run end");
            }
        }
    
        public void test(){
            System.out.println(Thread.currentThread().getName()+" begin");
            Thread p4 = new Thread(new PrimeRun());
            Thread p6 = new Thread(new PrimeRun());
            p4.setName("P4");
            p6.setName("P6");
            p4.start();
            p6.start();
            System.out.println(Thread.currentThread().getName()+" end");
        }
    
        public static void main(String[] args) {
            new ThreadPriorityTest().test();
        }
    }
    

    在 PrimeRun 类的 run() 方法中, 只是对 0 到 10 进行输出, 前面加上线程名字以识别。没有对线程进行设置, 按以上分析的 init() 方法可知, 优先级继承于 ThreadPriorityTest 中的优先级, 没进行设置优先级默认为 5。 输出如下:

    输出

    可以看到 p4 和 p6 的线程优先级都是 5, 输出是无序的, P4 和 P6 交叉输出, 因此每次的结果都不一样。

    指定优先级

    将线程中的优先级改一下, test() 函数变成如下:

    public void test(){
        System.out.println(Thread.currentThread().getName()+" begin");
        Thread p4 = new Thread(new PrimeRun());
        Thread p6 = new Thread(new PrimeRun());
        p4.setName("P4");
        p4.setPriority(4);
        p6.setName("P6");
        p6.setPriority(6);
        p4.start();
        p6.start();
        System.out.println(Thread.currentThread().getName()+" end");
    }
    

    在运行之后的输出如下:

    设置优先级后输出

    可以看到, P6 先于 P4 运行完。

    注意事项

    但是(一般 「但是」 后面的东西都要注意)

    优先级和操作系统及虚拟机版本相关。
    ++优先级只是代表告知了 「线程调度器」该线程的重要度有多大。如果有大量线程都被堵塞,都在等候运
    行,调试程序会首先运行具有最高优先级的那个线程。然而,这并不表示优先级较低的线程不会运行(换言之,不会因为存在优先级而导致死锁)。若线程的优先级较低,只不过表示它被准许运行的机会小一些而已。++

    因此, 在实际的编码时, 认为高优先级一定先于低优先级的线程执行, 最后会出问题的。

    优先级继承

    而关于特点 2 和 3 的区别, 我们在第一次 test() 时, P4 和 P6 的优先级都是 5, 我们将函数改一下:

     public void test(){
        Thread.currentThread().setPriority(10);
        System.out.println(Thread.currentThread().getName()+" begin");
        Thread p4 = new Thread(new PrimeRun());
        Thread p6 = new Thread(new PrimeRun());
        p4.setName("P4");
        p6.setName("P6");
        p4.start();
        p6.start();
        System.out.println(Thread.currentThread().getName()+" end");
    }
    

    在创建 P4 和 P6 之前将当前线程的优先级设置为 10, 并在 run() 中去掉一些无关的输出, 最后输入如下:

    继承优先级

  • 相关阅读:
    uboot和内核分区的修改
    2440移植内核到uboot上,打印乱码
    启动新内核出现:No filesystem could mount root, tried: ext3 ext2 cramfs vfa
    启动新内核出现:Kernel panic
    移植最新版本3.4.2内核
    2017团体程序设计天梯赛大区赛 L3-3 球队“食物链”
    leetcode543 Diameter of Binary Tree
    CF599B Spongebob and Joke
    poj1930 Dead Fraction
    poj3040 Allowance
  • 原文地址:https://www.cnblogs.com/homejim/p/9527226.html
Copyright © 2011-2022 走看看