1

    欢迎大家关注我的公众号"小猴子的技术笔记",有问题可以及时和我交流。
    我们知道在构建一个线程对象的时候可以给线程设置一个优先级,就像下面这样:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("设置线程的优先级");
    }
}
public class MyRunnableTest {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.setPriority(10);
        thread.start();
    }
}

    或许你曾经有过这样的想法,如果有多个线程的话,是不是可以按照这种优先级设置的顺序来启动线程呢?我们来看下面这个例子:

public class MinPriority implements Runnable {
    @Override
    public void run() {
        System.out.println("线程的优先级为1");
    }
}
public class NormalPriority implements Runnable {
    @Override
    public void run() {
        System.out.println("线程的优先级为5");
    }
}
public class MaxPriority implements Runnable {
    @Override
    public void run() {
        System.out.println("线程的优先级为10");
    }
}
public class ThreadPriorityTest {
    public static void main(String[] args) {
        Thread minThread = new Thread(new MinPriority());
        minThread.setPriority(1);
        Thread maxThread = new Thread(new MaxPriority());
        maxThread.setPriority(10);
        Thread normalThread = new Thread(new NormalPriority());
        normalThread.setPriority(5);
        minThread.start();
        maxThread.start();
        normalThread.start();
    }
}

    我模拟了三个不同优先级别的线程,在构建完成之后“同时”启动,然后观察结果。也请你尝试把这些代码拷贝到你的开发工具中,然后尝试运行“ThreadPriorityTest”,也许第一次你看到的结果是这样的:

线程的优先级为10
线程的优先级为5
线程的优先级为1

    你会很开心,因为它按照你的预期来输出了。但是,请尝试多运行几次“ThreadPriorityTest”你也许会发现有其他的不同的结果:

线程的优先级为5
线程的优先级为10
线程的优先级为1

    看到上面结果之后,回过头来看我们最初设置的线程的优先级貌似并没有起到什么作用。这到底是为什么呢?别着急!我们先来过一遍设置线程优先级的源码:

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);
    }
}

    首先声明了一个线程组对象,然后“checkAccess()”进行了安全检查,紧接着就是判断我们传递过来的优先级的值,判断它是不是低于最小的优先级,高于最大的优先级,如果满足上述条件的话,就直接抛出参数不合法的异常。
线程Thread类提供了三个优先级的常量:

// 可设置最小优先级
public final static int MIN_PRIORITY = 1;
// 默认的优先级,如果没设置的话,默认为此值
public final static int NORM_PRIORITY = 5;
// 可设置最大优先级
public final static int MAX_PRIORITY = 10;

    源码中比较重要的就是“((g = getThreadGroup()) != null)”的判断,第一步先通过“getThreadGroup()”方法获取到当前的线程组赋值给“g”。获取线程组“getThreadGroup()”方法的源码如下:


public final ThreadGroup getThreadGroup() {
    return group;
}

    拿到返回的线程组之后判断我们显示设置的线程优先级的值是否大于了线程组的优先级,如果大于了,就设置为线程组的优先级。

    最后就是通过“setPriority0(priority = newPriority)”方法给线程赋值:

private native void setPriority0(int newPriority);

    可以看到最后设置线程的这个方法是调用的本地方法,那么就是交由底层去实现的。

    其实线程的优先级设置可以理解为线程抢占CPU时间片的概率,虽然概率比较大,但是它不一定就是按照优先级的顺序去抢占CPU时间片的,具体的执行顺序还是要根据谁先抢到了CPU的时间片,谁就先来执行。

    因此千万不要把设置线程的优先顺序当做是线程实际启动的优先顺序哦!
    欢迎大家关注我的公众号"小猴子的技术笔记",有问题可以及时和我交流。


小猴子的技术笔记
15 声望1 粉丝