博主信息
小爱豆
博文
258
粉丝
0
评论
0
访问量
4924
积分:0
P豆:630

多线程详解之优先级

2021年10月24日 20:36:14阅读数:13博客 / 小爱豆

好久没更新了,最近半年有些忙碌,更换了新的工作,业务很多,责任也比以往重了许多,这更激发了我对知识的渴求。但好在现在适应了过来,接下来就是继续给自己充电,在未来承担更多的职责。

前文我们已经了解了线程的一些基础知识,这篇文章是对基础的一个补充。线程有个有趣的状态,叫RUNNABLE,之所以不叫RUNNING,是因为它表示线程处于一种可执行的状态,而不是已经在执行了。对一台电脑而言,CPU的个数和核心数都是有限的,但是它可以运行很多的程序,每个程序又可以创建很多个线程,所以不是每个线程一调用 start 方法就一定能马上运行,而是等待CPU有空闲的时间片时来调度。

CPU调度线程的策略是一门复杂而深刻的学问,需要我们掌握足够的操作系统知识之后才能理解透彻,但好在对我们理解线程没有太大的影响。我们所关心的,是如何能让我们创建的线程能够被系统优先执行呢?其实Java已经准备了解决方案。在 Thread 中,可以通过 setPriority(int newPriority) 方法为线程设置优先级,以下是该方法的定义:

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

MIN_PRIORITY 和 MAX_PRIORITY 是优先级的上下限,除此之外还有一个 NORM_PRIORITY,它们是定义在 Thread 中的静态常量:

/**
* 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;

也就是说,我们可以为线程设置 1-10 共 10 个等级的优先级,来对不同的任务进行分级,这样一来,我们就可以按照需要,让重要的任务先执行了。

接下来,我们通过一个例子,看一下优先级对线程调度的影响。假设有线程 AThread 和 BThread,它们处理的任务是相同的,但分配的优先级不同,线程的定义如下:

public class TestThread extends Thread {
    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        int sum = ;
        for (int i = ; i < 10000; i++) {
            // 耗时操作
            Random random = new Random();
            random.nextInt();
            sum += i;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Thread " + getName() + " used time " + (endTime - startTime) + " ms");
    }
}

测试时,我们以线程名称来区分 A 线程和 B 线程,QQ号码转让测试代码如下:

for (int i = ; i < 5; i++) {
    TestThread aThread = new TestThread();
    aThread.setName("A" + i);
    aThread.setPriority(Thread.MAX_PRIORITY);
    aThread.start();

    TestThread bThread = new TestThread();
    bThread.setName("B" + i);
    bThread.setPriority(Thread.MIN_PRIORITY);
    bThread.start();
}

先运行一次看下输出:

Thread A used time 11 ms
Thread A3 used time 10 ms
Thread A1 used time 10 ms
Thread A4 used time 10 ms
Thread A2 used time 10 ms
Thread B4 used time 13 ms
Thread B3 used time 13 ms
Thread B2 used time 15 ms
Thread B1 used time 15 ms
Thread B used time 15 ms

看起来十分符合我们的设想,设置了优先级后的确 A 线程更早更快的被执行了。但是再运行一下看看:

Thread A1 used time 9 ms
Thread A4 used time 9 ms
Thread A2 used time 10 ms
Thread B2 used time 11 ms
Thread B4 used time 11 ms
Thread B1 used time 13 ms
Thread A3 used time 13 ms
Thread A used time 14 ms
Thread B3 used time 13 ms
Thread B used time 14 ms

可以发现,这个优先级并不那么靠谱,看起来CPU会更倾向于先执行优先级高的线程,但不会把机会全部给到它,因此具有一定的随机性。而且题主使用的是 Windows 电脑,如果更换为 Mac 系统,你会发现设置优先级根本没有任何作用。(PS:看起来这个属性有点鸡肋呢~)

这里我们介绍优先级的概念不是为了让大家知道它很鸡肋,在某些系统上这个概念还是有很大使用价值的。另一方面也是提醒大家不要过分依赖这个属性,源代码里并没有交代它会在某些系统中无效,也没有说清楚它的随机性,这也说明只有实践才能出真知,即使是权威的、系统的东西也会有不精确的时候。


版权申明:本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!

全部评论

文明上网理性发言,请遵守新闻评论服务协议

条评论
  • 下面由Redis教栏目给大家介绍Redis6.0到底为何引入线?,希望对需要的朋友有所帮助!本文主要分两部分。首我们聊一下Redis6.0前为什么采用单线模型。

    2021-03-30

    955

    javascript是一种具有函数的轻量释型或即时编译型的编语言;JavaScript基于原型编范式的动态脚本语言,并且支持面向对象、命令式和声明式风格。
    JavaScript是一种具有函数的轻量释型或即时编译型的编语言;JavaScript基于原型编范式的动态脚本语言,并且支持面向对象、命令式和声明式风格。
    javascript是一门具有函数的轻量释型或即时编译型的编语言;JavaScript是基于原型编范式的动态脚本语言,并且支持面向对象、命令式和声明式风格。
    JavaScript是一种具有函数的轻量释型或即时编译型的编语言;JavaScript基于原型编范式的动态脚本语言,并且支持面向对象、命令式、声明式、函数式编范式。
    js全称JavaScript,是一种具有函数的轻量,直译式、释型或即时编译型的高语言,是一种属于网络的高脚本语言;JavaScript基于原型编范式的动态脚本语言,并且支持面向对象
    javascript由Netscape公司创建,是一种具有函数的轻量释型或即时编译型的编语言;JavaScript基于原型编范式的动态脚本语言,并且支持面向对象、命令式、声明式、函数式编范式
    javascript就是js,js是javascript的缩写,是一种具有函数的轻量释型或即时编译型的编语言;JavaScript是基于原型编范式的动态脚本语言,并且支持面向对象、命令式和声明式风格
    css的冲突是指当个CSS样式应用到同一个元素时,这些样式间可能存在对同一个属性的不同格式设置;当发生冲突时,浏览器通过遵循原则或者最近原则来决CSS冲突问题。

    2020-06-13

    3235

    JavaScript简称【JS】是一种具有函数的轻量释型或即时编译型的编语言,它作为开发Web页面的脚本语言而出名,但它也被用到了很非浏览器环境中,支持面向对象、命令式和声明式风格。
    虚拟内存是把外存当做内存来使用,即用硬盘来模拟内存使用,可以缓物理内存不足的压力,有利于提升资源使用率。