首页 > 编程笔记 > Java笔记 阅读:4

什么是线程优先级,Java设置线程优先级(附带实例)

每个线程都具有各自的优先级,线程的优先级可以表明该线程在程序中的重要性,如果有很多线程处于就绪状态,那么系统会根据优先级来决定首先使哪个线程进入运行状态。但这并不意味着低优先级的线程得不到运行,而只是它运行的概率比较小,如垃圾回收线程的优先级就较低。

Thread 类中包含的成员变量代表了线程的某些优先级,比如:
其中,每个线程的优先级都在 Thread.MIN_PRIORITY~Thread.MAX_PRIORITY,在默认情况下其优先级都是 Thread.NORM_ PRIORITY。每个新产生的线程都继承了父线程的优先级。

在多任务操作系统中,每个线程都会得到一小段 CPU 时间片运行,在时间结束时,将轮换另一个线程进入运行状态,这时系统会选择与当前线程优先级相同的线程予以运行。系统始终选择就绪状态下优先级较高的线程进入运行状态。

处于各个优先级状态下的线程的运行顺序如下图所示:


图 1 处于各个优先级状态下的线程的运行顺序

在图 1 中,优先级为 5 的线程 A 首先得到 CPU 时间片;当该时间结束后,轮换到与线程 A 相同优先级的线程 B;当线程 B 的运行时间结束后,会继续轮换到线程 A,直到线程 A 与线程 B 都执行完毕,才会轮换到线程 C;当线程 C 结束后,才会轮换到线程 D。

线程的优先级可以使用 setPriority() 方法进行调整,如果使用该方法设置的优先级不是 1~10,则将产生 IllegalArgumentException 异常。

【实例】创建 PriorityTest 类并实现 Runnable 接口,在 run() 方法中执行 5 万次字符串拼接。在主方法中以 PriorityTest 对象为参数创建 4 个线程,并分配不同的优先级,然后启动这些线程。
public class PriorityTest implements Runnable {
    String name;

    public PriorityTest(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        String tmp = "";
        for (int i = 0; i < 50000; i++) {
            tmp += i; //完成5万次字符串拼接
        }
        System.out.println(name + "线程完成任务");
    }

    public static void main(String[] args) {
        Thread a = new Thread(new PriorityTest("A"));
        a.setPriority(1); //A线程优先级最小
        Thread b = new Thread(new PriorityTest("B"));
        b.setPriority(3);
        Thread c = new Thread(new PriorityTest("C"));
        c.setPriority(7);
        Thread d = new Thread(new PriorityTest("D"));
        d.setPriority(10); //D线程优先级最大

        a.start();
        b.start();
        c.start();
        d.start();
    }
}
由于线程的执行顺序是由 CPU 决定的,即使线程设定了优先级也是作为 CPU 的参考数据,因此真实的运行结果可能并不一定按照优先级排序,例如笔者运行的结果如下:

D线程完成任务
B线程完成任务
C线程完成任务
A线程完成任务

从这个结果中可以看出,优先级最大的 D 线程是第一个完成的,优先级最小的 A 线程是最后一个完成的。但是,C 线程的优先级比B线程大,却仍然在 B 线程之后才完成,这是 CPU 的真实运行结果。

相关文章