Java 线程优先级不起作用

2022-09-03 16:22:28

这是一个关于线程优先级的测试。代码来自 Thinking in Java p.809

import java.util.concurrent.*;

public class SimplePriorities implements Runnable {
    private int countDown = 5;
    private volatile double d; // No optimization
    private int priority;

    public SimplePriorities(int priority) {
        this.priority = priority;
    }

    public String toString() {
        return Thread.currentThread() + ": " + countDown;
    }

    public void run() {
        Thread.currentThread().setPriority(priority);
        while (true) {
            // An expensive, interruptable operation:
            for (int i = 1; i < 10000000; i++) {
                d += (Math.PI + Math.E) / (double) i;
                if (i % 1000 == 0)
                    Thread.yield();
            }
            System.out.println(this);
            if (--countDown == 0)
                return;
        }
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++)
            exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
        exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
        exec.shutdown();
    }
}

我想知道为什么我无法获得常规结果,例如:

Thread[pool-1-thread-6,10,main]: 5 
Thread[pool-1-thread-6,10,main]: 4 
Thread[pool-1-thread-6,10,main]: 3 
Thread[pool-1-thread-6,10,main]: 2 
Thread[pool-1-thread-6,10,main]: 1 
Thread[pool-1-thread-3,1,main]: 5 
Thread[pool-1-thread-2,1,main]: 5 
Thread[pool-1-thread-1,1,main]: 5 
Thread[pool-1-thread-5,1,main]: 5 
Thread[pool-1-thread-4,1,main]: 5 
...

但是一个随机的结果(每次我运行它都会改变):

Thread[pool-1-thread-2,1,main]: 5
Thread[pool-1-thread-3,1,main]: 5
Thread[pool-1-thread-4,1,main]: 5
Thread[pool-1-thread-2,1,main]: 4
Thread[pool-1-thread-3,1,main]: 4
Thread[pool-1-thread-1,1,main]: 5
Thread[pool-1-thread-6,10,main]: 5
Thread[pool-1-thread-5,1,main]: 5
...

我使用i3-2350M 2C4T CPU与Win 7 64位JDK 7。这重要吗?


答案 1

Java 线程优先级不起作用

线程优先级高度特定于操作系统,并且在许多操作系统上通常具有最小的影响。优先级有助于仅对运行队列中的线程进行排序,并且不会更改线程以任何主要方式运行的频率,除非您在每个线程中执行大量 CPU。

您的程序看起来会占用大量 CPU,但除非您的内核数少于线程数,否则通过设置线程优先级,您可能不会看到输出顺序的任何变化。如果有空闲的 CPU,则甚至会安排一个优先级较低的线程运行。

此外,线程永远不会挨饿。在这种情况下,即使是优先级较低的线程也会有时间经常运行。您应该看到优先级较高的线程被分配了时间片以更频繁地运行,但这并不意味着优先级较低的线程将等待它们完成,然后再运行它们。

即使优先级确实有助于为一个线程提供比其他线程更多的CPU,线程程序也会受到争用条件的影响,这有助于为其执行注入大量的随机性。但是,您应该看到的是,最大优先级线程比其他线程更有可能更频繁地吐出其消息。如果将优先级添加到 中,这应该会在多次运行中变得很明显。0println()

同样重要的是要注意,编写IO的方法将极大地影响线程的交互方式以及不同线程相互阻塞的方式。此外,可以是 no-op,具体取决于操作系统如何执行其线程调度。System.out.println(...)synchronizedThread.yield();

但是一个随机的结果(每次我运行它都会改变):

右。线程化程序的输出很少是“完美的”,因为根据定义,线程是异步运行的。我们希望输出是随机的,因为我们希望线程彼此独立并行运行。这就是他们的力量。如果你期望一些精确的输出,那么你不应该使用线程。


答案 2

线程优先级取决于实现。特别是,在Windows中:

当所有线程都在争用 CPU 时,线程优先级并不是很有帮助。(来源)

《Java 并发实践》一书也说

避免使用线程优先级的诱惑,因为它们会增加对平台的依赖性,并可能导致活动问题。大多数并发应用程序可以对所有线程使用默认优先级。