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

Posted

技术标签:

【中文标题】Java 线程优先级如何转换为 OS 线程优先级?【英文标题】:How are Java Thread priorities translated to an OS thread priority? 【发布时间】:2010-09-22 19:20:08 【问题描述】:

Java API 线程优先级 (1-10) 如何转换为操作系统级别的优先级,因为大多数操作系统没有与此匹配的线程优先级(以数量计)。

因此请记住,是否存在两个或多个具有不同优先级的线程最终在操作系统级别获得相同优先级的情况。

请澄清,如果我的理解有一些更正。

【问题讨论】:

【参考方案1】:

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

Solaris

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

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

Linux

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

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

窗口

1 – 2 ⇒ THREAD_PRIORITY_LOWEST 3 - 4 ⇒ THREAD_PRIORITY_BELOW_NORMAL 5 - 6 ⇒ THREAD_PRIORITY_NORMAL 7 – 8 ⇒ THREAD_PRIORITY_ABOVE_NORMAL 9 – 10 ⇒ THREAD_PRIORITY_HIGHEST

【讨论】:

您是否有方便的参考资料,这是直接映射还是基于操作系统如何处理这些值的模拟? 没有官方文档,但是在OpenJDK源码中阅读hotspot/src/os/linux,solaris,win32/vm/os_linux,solaris,win32.cpp(搜索java_to_os_priority)价值。 :-) 那里也有详细说明:javamex.com/tutorials/threads/priority_what.shtml【参考方案2】:

您的理解是正确的 - Java 线程优先级并没有完全映射到 OS 线程优先级。

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

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

虽然您可以选择比这更精细,但您需要注意目标平台上可能会丢失任何更详细的信息。

【讨论】:

【参考方案3】:

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

$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

正是我们正在寻找的东西,不是吗?

【讨论】:

【参考方案4】:

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

基本上,除非 JRE 使用 POSIX 等第 3 方线程标准,而不是在内部实现所有内容,否则这将高于操作系统进程优先级。

【讨论】:

以上是关于Java 线程优先级如何转换为 OS 线程优先级?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA在语言级支持多线程

Android 设置线程优先级

Java多线程之线程状态总结

Java线程优先级

Java线程优先级

如何解决java 多线程问题