编译器忽略线程优先级

时间:2017-08-12 19:45:18

标签: java multithreading

我试图用Bruce Eckel的Thinking in Java编译这个例子:

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 < 100000; 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
...

但在我的情况下,第6个线程最初不执行任务,线程无序。你能解释一下我有什么问题吗?我只是复制了源代码并没有添加任何代码字符串。

2 个答案:

答案 0 :(得分:0)

代码工作正常,并附有书中的输出。

你的IDE可能有滚动条的控制台窗口 - 只需向上滚动它,看第6个线程首先完成它的工作。

但是,结果可能因操作系统/ JVM版本而异。此代码在Windows 10 / JVM 8上按预期运行

答案 1 :(得分:0)

这里有两个问题:

如果两个具有相同优先级的线程想要写输出,哪一个先行?

线程的顺序(具有相同的优先级)是未定义的,因此输出的顺序是未定义的。很可能允许单个线程连续写入多个输出(因为这是大多数线程调度程序的工作方式),但也可能是完全随机的,或介于两者之间的任何内容。

缓存的线程池将创建多少个线程?

这取决于你的系统。如果你在双核系统上运行,创建4个以上的线程毫无意义,因为几乎没有任何CPU可用于执行这些线程。在此方案中,只有在先前的任务完成后,其他任务才会排队并执行。

提示:还有一个固定大小的线程池,试验它应该改变输出。

总而言之,您的代码没有任何问题,假设线程以任何顺序执行是错误的。甚至在技术上可能(尽管非常不可能),第一个任务在最后一个任务开始之前就已经完成了。如果您的图书说上面的订单是&#34;正确&#34;那本书完全错了。在一个可能是最有可能的输出的平均系统上,但是 - 如上所述 - 除了你强制执行它之外,线程永远不会有任何顺序。

强制执行它的一种方法是线程优先级 - 更高优先级将首先完成工作 - 您可以在concurrent package中找到其他概念。