线程的优先级

在操作系统中,线程可以划分优先级,优先级较 高的线程得到 CPU 资源较多,也就是CPU优先执行优 先级较高的线程对象中的任务,其实就是让高优先级 的线程获得更多的 CPU时间片。 设置线程优先级有助于 “ 线程规划器 ”确定在下一 次选择哪一个线程来优先执行。

设置线程的优先级使用setPriority()方法

/**
     * Changes the priority of this thread.
     * <p>
     * First the <code>checkAccess</code> method of this thread is called
     * with no arguments. This may result in throwing a
     * <code>SecurityException</code>.
     * <p>
     * Otherwise, the priority of this thread is set to the smaller of
     * the specified <code>newPriority</code> and the maximum permitted
     * priority of the thread's thread group.
     *
     * @param newPriority priority to set this thread to
     * @exception  IllegalArgumentException  If the priority is not in the
     *               range <code>MIN_PRIORITY</code> to
     *               <code>MAX_PRIORITY</code>.
     * @exception  SecurityException  if the current thread cannot modify
     *               this thread.
     * @see        #getPriority
     * @see        #checkAccess()
     * @see        #getThreadGroup()
     * @see        #MAX_PRIORITY
     * @see        #MIN_PRIORITY
     * @see        ThreadGroup#getMaxPriority()
     */
    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

线程优先级等级1~10

在 Java 中,线程的优先级分为 1 ~ 10 共 10个等级, 如果优先级小于 1 或大于 10 ,则 JDK 抛出异常throw new IllegalArgumentException() 。

预置定义优先级的值

JDK使用3个常量来预置定义优先级的值

/**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

线程优先级的继承特性

在 Java 中,线程的优先级具有继承性,例如, A线程启 动 B 线程,则 B 线程的优先级与 A 线程是一样的。

MyThread1.java

package test1_14;

public class MyThread1 extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread1 run priority=" + this.getPriority());
        MyThread2 thread2 = new MyThread2();
        thread2.start();
    }
}

MyThread2.java

package test1_14;

public class MyThread2 extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread2 run priority=" + this.getPriority());
    }
}

Run.java

package test1_14;

public class Run {
    public static void main(String[] args) {
        System.out.println("main thread begin priority=" + Thread.currentThread().getPriority());
        // Thread.currentThread().setPriority(6);
        System.out.println("main thread end priority=" + Thread.currentThread().getPriority());
        MyThread1 thread1 = new MyThread1();
        thread1.start();
    }
}

运行结果

java 优先级注解 java设置优先级_java

优先级被继承

去掉以下注释的运行结果

// Thread.currentThread().setPriority(6);

java 优先级注解 java设置优先级_优先级_02

 

优先级被更改再继续继承

优先级的规律性

虽然使用 setPriority()方法可以设置线程的优先级,但还没有看到设置优先级所带来的效果。

MyThread1.java

package test1_14.test1;

import java.util.Random;

public class MyThread1 extends Thread {
    @Override
    public void run() {
        long beginTime = System.currentTimeMillis();
        long addResult = 0;
        for (int j = 0; j < 10; j++) {
            for (int i = 0; i < 50000; i++) {
                Random random = new Random();
                random.nextInt();
                addResult = addResult + i;
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("★★★★★thread 1 use time=" + (endTime - beginTime));
    }
}

MyThread2.java

package test1_14.test1;

import java.util.Random;

public class MyThread2 extends Thread {
    @Override
    public void run() {
        long beginTime = System.currentTimeMillis();
        long addResult = 0;
        for (int j = 0; j < 10; j++) {
            for (int i = 0; i < 50000; i++) {
                Random random = new Random();
                random.nextInt();
                addResult = addResult + i;
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("☆☆☆☆☆thread 2 use time=" + (endTime - beginTime));
    }
}

Run.java

package test1_14.test1;

public class Run {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            MyThread1 thread1 = new MyThread1();
            thread1.setPriority(10);
            thread1.start();
            MyThread2 thread2 = new MyThread2();
            thread2.setPriority(1);
            thread2.start();
        }
    }
}

输出结果

java 优先级注解 java设置优先级_优先级_03

可以发现,高优先级的线程总是大部分先执行 完,但不代表高优先级的线程全部先执行完。另外,并不是 MyThread1 线程先被 main线程调用就先执行完,出现这种结果是 因为 MyThread1 线程的优先级是最高级别10。当线程优先级的等 级差距很大时,谁先执行完和代码的调用顺序无关

为了验证这 个结论,修改Run.java代码

package test1_14.test2;

import test1_14.test1.MyThread1;
import test1_14.test1.MyThread2;

public class Run {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            MyThread1 thread1 = new MyThread1();
            thread1.setPriority(1);
            thread1.start();
            MyThread2 thread2 = new MyThread2();
            thread2.setPriority(10);
            thread2.start();
        }
    }
}

输出结果

java 优先级注解 java设置优先级_java_04

大部分thread2先执行完,这就验证线 程的优先级与代码执行顺序无关,出现这种结果是因为 MyThread2的优先级是最高的,说明线程的优先级具有一定的规 律性,即 CPU 尽量将执行资源让给优先级比较高的线程。

优先级的随机性

前面案例介绍了线程具有优先级,优先级高的线程往往优先执行完,但这个结果不是绝对的,因为线程的优先级还具有 “随 机性 ” ,即优先级较高的线程不一定每一次都先执行完。


为了让结果体现 “ 随机性 ”,将两个线程的优先级分别设置为 5 、 6 ,让优先级接近一些。


MyThread1.java

package test1_14.test3;

import java.util.Random;

public class MyThread1 extends Thread {
    @Override
    public void run() {
        long beginTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            Random random = new Random();
            random.nextInt();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("★★★★★thread 1 use time=" + (endTime - beginTime));
    }
}

MyThread2.java

package test1_14.test3;

import java.util.Random;

public class MyThread2 extends Thread {
    @Override
    public void run() {
        long beginTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            Random random = new Random();
            random.nextInt();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("☆☆☆☆☆thread 2 use time=" + (endTime - beginTime));
    }
}

Run.java

package test1_14.test3;

public class Run {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            MyThread1 thread1 = new MyThread1();
            thread1.setPriority(5);
            thread1.start();
            MyThread2 thread2 = new MyThread2();
            thread2.setPriority(6);
            thread2.start();
        }
    }
}

运行结果

java 优先级注解 java设置优先级_java 优先级注解_05

交错执行完

根据此案例可以得出一个结论,优先级较高的线程并不一定 每一次都先执行完run()方法中的任务,也就是线程优先级与输出 顺序无关,这两者并没有依赖关系,它们具有不确定性、随机 性。

优先级对线程运行速度的影响

Run.java

package test1_14.test4;

public class Run {
    public static void main(String[] args) {
        try {
            ThreadA a = new ThreadA();
            a.setPriority(Thread.NORM_PRIORITY - 3);
            a.start();
            ThreadB b = new ThreadB();
            b.setPriority(Thread.NORM_PRIORITY + 3);
            b.start();
            Thread.sleep(20000);
            a.stop();
            b.stop();
            System.out.println("a=" + a.getCount());
            System.out.println("b=" + b.getCount());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果 

java 优先级注解 java设置优先级_System_06


优先级高的运行得快