好久没更新了,最近半年有些忙碌,更换了新的工作,业务很多,责任也比以往重了许多,这更激发了我对知识的渴求。但好在现在适应了过来,接下来就是继续给自己充电,在未来承担更多的职责。
前文我们已经了解了线程的一些基础知识,这篇文章是对基础的一个补充。线程有个有趣的状态,叫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 = 0;
for (int i = 0; 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 线程,测试代码如下:
for (int i = 0; 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 A0 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 B0 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 A0 used time 14 ms
Thread B3 used time 13 ms
Thread B0 used time 14 ms
可以发现,这个优先级并不那么靠谱,看起来CPU会更倾向于先执行优先级高的线程,但不会把机会全部给到它,因此具有一定的随机性。而且题主使用的是 Windows 电脑,如果更换为 Mac 系统,你会发现设置优先级根本没有任何作用。(PS:看起来这个属性有点鸡肋呢~)
这里我们介绍优先级的概念不是为了让大家知道它很鸡肋,在某些系统上这个概念还是有很大使用价值的。另一方面也是提醒大家不要过分依赖这个属性,源代码里并没有交代它会在某些系统中无效,也没有说清楚它的随机性,这也说明只有实践才能出真知,即使是权威的、系统的东西也会有不精确的时候。