Java Thread优先级如何转换为OS线程优先级?

由于大多数操作系统没有与此匹配的线程优先级(就数量而言),因此java API线程优先级(1-10)如何转换为操作系统级优先级。

所以请记住,当两个或多个具有不同优先级的线程最终在操作系统级别获得相同的优先级时,会出现这种情况。

如果我的理解有所改正,请澄清一下。

实际上,某些优先级可以映射到相同的“本机”优先级。 这是列表(基于OpenJDK 6中的热点代码):

的Solaris

  • 1⇒0
  • 2⇒32
  • 3⇒64
  • 4⇒96
  • 5 – 10⇒127

值得注意的是,在Solaris上,您不能将线程优先级提高到正常范围以上,只能降低它:5的优先级值与任何更高的值相同。

Linux的

  • 1 – 10⇒4 – -5( nice值)

值得注意的是,在Linux上,Java中的不同线程优先级确实映射到本机级别的不同优先级值。

视窗

  • 1 – THREAD_PRIORITY_LOWEST
  • 3 – THREAD_PRIORITY_BELOW_NORMAL
  • 5 – THREAD_PRIORITY_NORMAL
  • 7 – THREAD_PRIORITY_ABOVE_NORMAL
  • 9 – THREAD_PRIORITY_HIGHEST

您的理解是正确的 – Java线程优先级不能完全映射到OS线程优先级。

因此,如果您的算法以任何方式依赖于线程优先级映射的细节,那么它就会被破坏,因为它会根据这么多变量而变化。 例如,升级您的JRE或将补丁/ Service Pack应用到您的操作系统可能会破坏它 – 当然,只是在不同的操作系统上运行也会产生影响。

除非在非常特殊的情况下,仅使用两个优先级就足够了 – 正常和低。 大多数工作将在普通线程中完成。 低优先级应该保留给那些不能让普通优先级的线程饿死的线程,而只是吞噬并没有使用的处理器电源。

虽然如果您选择,您可以获得比这更细粒度的内容,但您需要注意,目标平台上可能会丢失更多细节。

我对Linux上的Sun JVM不太确定。 写了一个快速的Java proggy以产生每个优先级的10个线程并计算pi(4 * atan(1)方法),每个BigDecimals 500,000次,加入每个线程并报告run方法的运行时间。 是的,可能不是最好的例子,但保持基本。

 $uname -r && grep bogomips /proc/cpuinfo 2.4.33.3 bogomips : 4312.26 $java -version 2>&1 |head -1 Java version "1.6.0_01" $javac T.java && java -Xmx32m T 1:3112 2:2636 3:2662 4:3118 5:2870 6:3319 7:3412 8:3304 9:3299 10:3069 

看起来没有人会期待的偏差! 那是在一台小型虚拟Linux机器上。 让我们尝试一下真正的平板以防万一,这个盒子相当活跃,平均负载很少低于7,让我们看看我们如何安排在这样的环境中:

 $uname -r && grep bogomips /proc/cpuinfo 2.6.9-67.ELsmp bogomips : 3992.93 bogomips : 3990.00 $java -version 2>&1 |head -1 java version "1.4.2_14" $javac T.java && java -Xmx32m T 1:63200 2:64388 3:62532 4:58529 5:62292 6:64872 7:64885 8:64584 9:61653 10:61575 

嗯,这里没有太大的变化,不知道1.4甚至是映射线程。 我们来试试一个Windows框。 我知道Windows有一个相当激进的线程优先级架构。 任何高于正常情况的事物都会消耗更多。 因此,让我们在每个线程中突破900,000次迭代:

 C:\>java -version java version "1.6.0_11" C:\>java -Xmx32m T 1:12578 2:12625 3:11469 4:11453 5:10781 6:8937 7:10516 8:8406 9:9953 10:7391 

我们正在寻找什么,不是吗?

既然我们在谈论线程,我认为这永远不会直接到达操作系统。 优先级可能是JRE关于如何为每个线程安排CPU时间的提示。 要处理你的例子,需要某种“打破平局”的算法。

基本上,除非JRE使用像POSIX这样的第三方线程标准,而不是在内部实现所有内容,否则这将成为操作系统进程优先级的首选。