每个线程均有优先级,在 Thread 中, 与优先级对应的属性如下:
/** * 线程的优先级属性 */ private int priority; /** * 线程所能拥有的最大优先级. */ public final static int MIN_PRIORITY = 1; /** * 线程默认的优先级. */ public final static int NORM_PRIORITY = 5; /** * 线程所能拥有的最大优先级. */ public final static int MAX_PRIORITY = 10; 相关函数在此只讨论 Thread 类中的。
优先级初始化 private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) { // .... this.priority = parent.getPriority(); setPriority(priority); // .... }init() 函数对优先级进行了初始化。并调用 setPriority(priority) 函数进行设置。从中得知, 线程的优先级是继承于创建它的线程的。
设置优先级在 init() 中, 除了给 this.priority 赋值, 还调用了 setPriority(priority) 函数, 因为在该函数内部还调用了一个 native 方法。
public final void setPriority(int newPriority) { ThreadGroup g; checkAccess(); // 不能大于最大优先级 MAX_PRIORITY if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if((g = getThreadGroup()) != null) { // 如比所属线程组的最大优先级还大, 则取线程组的最大优先级 if (newPriority > g.getMaxPriority()) { newPriority = g.getMaxPriority(); } setPriority0(priority = newPriority); } }由代码可知, 设置的优先级不能大于最大优先级,也不能大于所在线程组的最高优先级
获取优先级获取当前的优先级, 其实就是返回 priority 属性的值。
public final int getPriority() { return priority; }从以上可知, 在 Thread 中, 线程的优先级有如下特点:
Java 线程的优先级从 1~10;
Java 线程默认优先级是 5;
Java 线程的优先级继承于创建它的线程。
是不是感觉 2 和 3 有所矛盾呢?可以在后面的代码和结果中找答案。
默认优先级先上代码来感受一下线程优先级的作用:
public class ThreadPriorityTest { class PrimeRun implements Runnable { public void run() { System.out.println(Thread.currentThread().getName() +"::"+ Thread.currentThread().getPriority()); System.out.println(Thread.currentThread().getName() + " Run begin"); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+"::"+i); } System.out.println(Thread.currentThread().getName() + " Run end"); } } public void test(){ System.out.println(Thread.currentThread().getName()+" begin"); Thread p4 = new Thread(new PrimeRun()); Thread p6 = new Thread(new PrimeRun()); p4.setName("P4"); p6.setName("P6"); p4.start(); p6.start(); System.out.println(Thread.currentThread().getName()+" end"); } public static void main(String[] args) { new ThreadPriorityTest().test(); } }在 PrimeRun 类的 run() 方法中, 只是对 0 到 10 进行输出, 前面加上线程名字以识别。没有对线程进行设置, 按以上分析的 init() 方法可知, 优先级继承于 ThreadPriorityTest 中的优先级, 没进行设置优先级默认为 5。 输出如下:
可以看到 p4 和 p6 的线程优先级都是 5, 输出是无序的, P4 和 P6 交叉输出, 因此每次的结果都不一样。
指定优先级将线程中的优先级改一下, test() 函数变成如下:
public void test(){ System.out.println(Thread.currentThread().getName()+" begin"); Thread p4 = new Thread(new PrimeRun()); Thread p6 = new Thread(new PrimeRun()); p4.setName("P4"); p4.setPriority(4); p6.setName("P6"); p6.setPriority(6); p4.start(); p6.start(); System.out.println(Thread.currentThread().getName()+" end"); }在运行之后的输出如下:
可以看到, P6 先于 P4 运行完。
注意事项但是(一般 「但是」 后面的东西都要注意)
优先级和操作系统及虚拟机版本相关。
++优先级只是代表告知了 「线程调度器」该线程的重要度有多大。如果有大量线程都被堵塞,都在等候运
行,调试程序会首先运行具有最高优先级的那个线程。然而,这并不表示优先级较低的线程不会运行(换言之,不会因为存在优先级而导致死锁)。若线程的优先级较低,只不过表示它被准许运行的机会小一些而已。++
因此, 在实际的编码时, 认为高优先级一定先于低优先级的线程执行, 最后会出问题的。
优先级继承