java API线程优先级(1-10)如何转换为操作系统级别的优先级,因为大多数操作系统没有与此匹配的线程优先级(以数量计)。
所以请记住,是否存在两个或多个具有不同优先级的线程最终在操作系统级别获得相同优先级的情况。
请澄清,如果我的理解有一些更正。
java API线程优先级(1-10)如何转换为操作系统级别的优先级,因为大多数操作系统没有与此匹配的线程优先级(以数量计)。
所以请记住,是否存在两个或多个具有不同优先级的线程最终在操作系统级别获得相同优先级的情况。
请澄清,如果我的理解有一些更正。
实际上,某些优先级可以映射到相同的“本机”优先级。以下是列表(基于 OpenJDK 6 中的 Hotspot 代码):
值得注意的是,在 Solaris 上,您不能将线程优先级提高到高于正常值,只能降低它:5 的优先级值与任何更高的值相同。
nice
数值)值得注意的是,在 Linux 上,Java 中不同的线程优先级确实映射到本机级别的不同优先级值。
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_HIGHEST
您的理解是正确的——Java 线程优先级并没有完全映射到 OS 线程优先级。
结果,如果您的算法以任何方式依赖于线程优先级映射的细节,那么它就会被破坏,因为它会根据如此多的变量而变化。例如,升级您的 JRE 或将补丁/服务包应用到您的操作系统可能会破坏它 - 当然,只是在不同的操作系统上运行也会产生后果。
除非在非常不寻常的情况下,仅使用两个优先级就足够了 - 正常和低。大多数工作将在普通线程中完成。低优先级应该保留给不能让正常优先级的线程饿死的线程,而只是狼吞虎咽并且不使用处理器能力。
虽然您可以选择比这更细粒度,但您需要注意目标平台上可能会丢失任何更详细的信息。
我不太确定 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
非常我们正在寻找的东西,不是吗?
由于我们谈论的是线程,我认为这永远不会直接到达操作系统。优先级可能是 JRE 关于如何调度每个线程的 CPU 时间的提示。要处理您的示例,需要某种“打破平局”算法。
基本上,这将在操作系统进程优先级之上,除非 JRE 使用 POSIX 之类的第 3 方线程标准,而不是在内部实现所有内容。