Java的每个线程都有一个优先级,当有多个线程处于就绪状态时,线程调度程序根据线程的优先级调度线程运行。
可以用下面方法设置和返回线程的优先级。
public final void setPriority(int newPriority) 设置线程的优先级。
public final int getPriority() 返回线程的优先级。
newPriority为线程的优先级,其取值为1到10之间的整数,也可以使用Thread类定义的常量来设置线程的优先级,这些常量分别为:Thread.MIN_PRIORITY、Thread.NORM_PRIORITY、Thread.MAX_PRIORITY,它们分别对应于线程优先级的1、5和10,数值越大优先级越高。当创建Java线程时,如果没有指定它的优先级,则它从创建该线程那里继承优先级。
不过设置优先级后有没有效果呢?
有人讲有,有人讲没有。如果是底层操作系统不支持优先级,那估计JVM也没办法;通常的Window系统和Linux系统还是支持优先级的,设置后是不是有效果呢?光是理论分析,难以有直观的认识,还是做个实验来看看吧。
操作系统是Windows XP SP3,CPU是AMD FX-5000四核 2.21GHz,内存2G。
import java.util.Random; public class HardJob extends Thread { private volatile boolean running = true; public HardJob(String name) { super(name); } public void shutdown() { running = false; } public void run() { double result = 0; int cnt = 0; Random randGen = new Random(); System.out.println(this.getName() + "(Priority " + this.getPriority() + "), begin to run."); while (running) { result += Math.sin(randGen.nextDouble() * 2 * Math.PI); cnt++; } System.out.println(this.getName() + "(Priority " + this.getPriority() + "), run " + cnt + " times."); } }
线程启动后,会不断执行正弦运算,直到被shutdown,最后输出执行的运算次数。
public class HardJobTest { /** * @param args */ public static void main(String[] args) { //给主线程设置最高优先级,以保证shutdown命令能按时发出去。 Thread.currentThread().setPriority(Thread.MAX_PRIORITY); //创建一个线程数组 HardJob arrJob[] = new HardJob[2]; for (int i = 0; i < arrJob.length; i++) { arrJob[i] = new HardJob("job" + String.valueOf(i + 1)); //给各个线程分别设置优先级,可根据需要进行修改。 arrJob[i].setPriority(i + 2); } for (int i = 0; i < arrJob.length; i++) { arrJob[i].start(); } try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for (int i = 0; i < arrJob.length; i++) { arrJob[i].shutdown(); } } }
测试程序刚开始启动若干个子线程,设置优先级,然后主线程休眠10秒钟,醒来后,关掉所有子线程;子线程接到指令后停止循环,输出执行的运算次数。
1. 只启动一个子线程,优先级分别设置为1, 5, 10。
三次的测试结果分别为:
job1(Priority 1), run 46754702 times.
job1(Priority 5), run 46538646 times.
job1(Priority 10), run 47020496 times.
三次执行次数差不多,都是四千多万次;CPU使用率为25-27%,我的机器为四核CPU,可以认为这个线程占用了一个CPU。
2. 启动两个子线程
优先级都设置为5,测试结果为:
job1(Priority 5), run 46572545 times.
job2(Priority 5), run 46625719 times.
CPU使用率为50-52%。
优先级分别设置为1和10,测试结果为:
job2(Priority 10), run 46704322 times.
job1(Priority 1), run 46303699 times.
CPU使用率为50-52%。
执行次数差不多,都是四千多万次,可以认为这两个线程各占用了一个CPU。
3. 启动四个子线程
优先级都设置为5,测试结果为:
job3(Priority 5), run 46512541 times.
job1(Priority 5), run 46630886 times.
job2(Priority 5), run 46442715 times.
job4(Priority 5), run 46913636 times.
CPU使用率为100%。
优先级分别设置为2、4、6、8,测试结果为:
job3(Priority 6), run 45987741 times.
job1(Priority 2), run 43118444 times.
job4(Priority 8), run 46514473 times.
job2(Priority 4), run 45445105 times.
CPU使用率为100%。
执行次数差不多,都是四千多万次,优先级为8的线程比优先级为2的线程略微多执行了些。
从结果上来看,可以认为这四个线程各占用了一个CPU。
4. 启动八个子线程
优先级都设置为5,测试结果为:
job1(Priority 5), run 23397717 times.
job3(Priority 5), run 23019800 times.
job5(Priority 5), run 23014664 times.
job8(Priority 5), run 23414866 times.
job2(Priority 5), run 22976901 times.
job6(Priority 5), run 23310006 times.
job4(Priority 5), run 23506321 times.
job7(Priority 5), run 23073406 times.
CPU使用率为100%。
执行次数只有之前的一半左右,可以近似认为每两个线程平分一个CPU。
优先级分别设置为2到9,测试结果为:
job7(Priority 8), run 46729368 times.
job8(Priority 9), run 47380536 times.
job6(Priority 7), run 46659873 times.
job4(Priority 5), run 19932864 times.
job5(Priority 6), run 24848567 times.
job2(Priority 3), run 526607 times.
job3(Priority 4), run 185692 times.
job1(Priority 2), run 230829 times.
CPU使用率为100%。
优先级为2、3、4的线程只执行了不到六十万次运算;
优先级为5、6的线程执行了约两千万次,
优先级为7、8、9的线程都执行了四千多万次,属于满负荷运行;
看来线程优先级还是有用的。
5. 启动16个子线程
优先级分别设置为2到9,测试结果为:
job8(Priority 9), run 47253075 times.
job6(Priority 7), run 23552148 times.
job7(Priority 8), run 23220591 times.
job15(Priority 8), run 21735566 times.
job14(Priority 7), run 23148908 times.
job16(Priority 9), run 46963640 times.
job5(Priority 6), run 206322 times.
job4(Priority 5), run 174672 times.
job2(Priority 3), run 282183 times.
job13(Priority 6), run 0 times.
job11(Priority 4), run 0 times.
job3(Priority 4), run 547 times.
job9(Priority 2), run 0 times.
job12(Priority 5), run 0 times.
job10(Priority 3), run 0 times.
job1(Priority 2), run 233635 times.
CPU使用率为100%。
优先级为9的线程执行了四千多万次,属于满负荷运行;
优先级为7、8的线程执行了二千多万次;
其他线程执行了不到三十万次。
从实验结果来看,如果CPU有空闲,即使是低优先级的线程,也可以得到足够的执行时间,接近满负荷执行。
如果CPU比较繁忙,优先级的作用就体现出来了,优先级高的线程能得到比较多的执行时间,优先级比较低的线程也能得到一些执行时间,但会少一些;CPU越繁忙,差异通常越明显。