线程优先级只使用三个等级

线程的优先级(Priority)决定了线程获得CPU运行的机会,优先级越髙获得的运行机 会越大,优先级越低获得的机会越小。Java的线程有10个级别(准确地说是11个级别,级 别为〇的线程是JVM的,应用程序不能设置该级别),那是不是说级别是10的线程肯定比 级别为9的线程先运行呢?我们来看如下一个多线程类:

public class TestPriorityThread implements Runnable{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<100000;i++){
			//消耗CPU的计算,性能差的机器,请修改循环限制 
			Math.hypot(Math.pow(924526789, i), Math.cos(i));
		}
		//输出线程优先级
		System.out.println("Priority:"+Thread.currentThread().getPriority());
	}
	
	
	public void start(int _priority){
		Thread t=new Thread(this);
		//设置线程优先级
		t.setPriority(_priority);
		t.start();
	}

}


该多线程类实现了 Runnable接口,实现了 nm方法,注意在run方法中有一个比较占用 CPU的计算,该计算毫无意义,只是为了保证一个线程尽可能多地消耗CPU资源,目的是 为了观察CPU繁忙时不同优先级线程的执行顺序。需要说明的是,如果此处使用了Thread. sleep()方法,则不能体现出线程优先级的本质了,因为CPU并不繁忙,线程调度不会遵循 优先级顺序来进行调度。

客户端的代码如下:

public static void main(String[] args) {
		for(int i=0;i<20;i++){
			new TestPriorityThread().start(i%10+1);
		}
	}

这里创建了 20个线程,每个线程在运行时都耗尽了 CPU资源,因为优先级不同,线程调 度应该最先处理优先级最高的,然后处理优先级最低的,也就是先执行2个优先级为10的线程,然后执行2个优先为9的线程,2个优先级为8的线程……但是结果却并不是这样的。

Priority:10 Priority:9 Priority:10 Priority:9 Priority:7 Priority:7Priority:8 Priority:8 Priority:5 Priority:5 Priority:6 Priority:6 Priority:4Priority:4 Priority:3 Priority:3 Priority:1 Priority:1 Priority:2

Priority:2                             .

println方法虽然有输出损耗,可能会影响到输出结果,但是不管运行多少次,你都会发现两个不争的事实:

(1)  并不是严格遵照线程优先级别来执行的

比如线程优先级为9的线程可能比优先级为10的线程先执行,优先级为1的线程可能比优先级为2的线程先执行,但很少会出现优先级为2的线程比优先级为10的线程先执行 (这里用了一个词“很少”,是说确实有可能出现,只是几率非常低,因为优先级只是表示线程获得CPU运行的机会,并不代表强制的排序号)。

(2)  优先级差别越大,运行机会差别越明显

比如优先级为10的线程通常会比优先级为2的线程先执行,但是优先级为6的线程和优先级为5的线程差别就不太明显了,执行多次,你会发现有不同的顺序。

这两个现象是线程优先级的一个重要表现,之所以会出现这种情况,是因为线程运行是需要获得CPU资源的,那谁能决定哪个线程先获得哪个线程后获得呢?这是依照操作系统设定的线程优先级来分配的,也就是说,每个线程要运行,需要操作系统分配优先级和CPU 资源,对于Java来说,JVM调用操作系统的接口设置优先级,比如Windows操作系统是通 过调用SetThreadPriority函数来设置的,问题来了:不同的操作系统线程优先级都相同吗?

这是个好问题。事实上,不同的操作系统线程优先级是不相同的,Windows有7个优先 级,Linux有140个优先级,Freebsd则有255个(此处指的是优先级总数,不同操作系统有 不同的分类,如中断级线程、操作系统级等,各个操作系统具体用户可用的线程数量也不相同)。Java是跨平台的系统,需要把这个10个优先级映射成不同操作系统的优先级,于是界定了 Java的优先级只是代表抢占CPU的机会大小,优先级越髙,抢占CPU的机会越大,被优先执行的可能性越高,优先级相差不大,则抢占CPU的机会差别也不大,这就是导致了 优先级为9的线程可能比优先级为10的线程先运行。

Java的缔造者们也察觉到了线程优先问题,于是在Thread类中设置了三个优先级,此 意就是告诉开发者,建议使用优先级常量,而不是1到10随机的数字。常量代码如下:

public class Thread implementsRunnable {

//最低优先级

public final static int MIN一PRIORITY = 1;

//普通优先级,默认值

public final static int NORM一PRIORITY = 5;

//最高优先级

public final static int MAX一PRIORITY = 10;

}


在编码时直接使用这些优先级常量,可以说在大部分情况下max_priority的线程会 比NORM_PRIORITY的线程先运行,但是不能认为必然会先运行,不能把这个优先级做为核心业务的必然条件,Java无法保证优先级高肯定会先执行,只能保证髙优先级有更多的执 行机会。因此,建议在开发时只使用此三类优先级,没有必要使用其他7个数字,这样也可以保证在不同的操作系统上优先级的表现基本相同。

明白了这个问题,那可能有读者要问了:如果优先级相同呢?这很好办,也是由操作系统决定的,基本上是按照FIFO原则(先入先出,First Input First Output),但也是不能完全保证。 注意线程优先级推荐使用MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY三个 级别,不建议使用其他7个数字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你是我的天晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值