在Java 6中,为什么即使优先级较低的线程产生,优先级较高的线程也不会运行?

在下面的代码中,我试图通过产生优先级较低的线程来获得更高优先级的线程。 但它似乎不起作用,优先级较高的线程似乎在较低优先级的线程完成后运行。 谁能解释我做错了什么?

import java.util.ArrayList; import java.util.List; public class TestThreadPriority extends Thread { static List messages = new ArrayList(); public void run() { Thread t = Thread.currentThread(); int priority = t.getPriority(); String name = t.getName(); messages.add(name + ":" + priority); Thread.yield(); messages.add(name + ":" + priority); } public static void main(String[] args) { // TODO Auto-generated method stub Thread t = Thread.currentThread(); t.setPriority(MIN_PRIORITY); int priority = t.getPriority(); String name = t.getName(); messages.add(name + ":" + priority); Thread tp1 = new TestThreadPriority(); tp1.setPriority(MIN_PRIORITY); Thread tp2 = new TestThreadPriority(); tp2.setPriority(MAX_PRIORITY); tp1.start(); tp2.start(); Thread.yield(); messages.add(name + ":" + priority); for(int i = 0; i < messages.size(); i++) { System.out.println((i+1) + ". " + messages.get(i)); } } } 

输出是:

  1. 主:1
  2. 线程0:1
  3. 线程0:1
  4. 主:1
  5. 线程1:10
  6. 线程1:10

任何帮助是极大的赞赏。

谢谢,Quadir

我猜你的第一个线程甚至在第二个线程启动之前就已经完成了。 也许如果你的线程做了一些真正的工作(或者甚至只是睡了一下),你会看到来自两个线程的重叠消息。

您的代码的另一个问题是您正在从多个线程访问messages而不进行同步。

在尝试打印messages内容之前,您还应该加入已经启动的两个线程,以确保您启动的线程已经记录了他们的消息,并且在您迭代时他们不会尝试修改列表它来打印它。

一旦你解决了这一切,最后一点是你的线程都在屈服,而不仅仅是优先级较低的线程。 当优先级较高的线程产生时,优先级较低的线程获得一些运行时间是完全合理的。 拥有更高的优先权并不会给你带来垄断。 在您的简化代码示例中,优先级可能不会对发生的情况产生太大影响 – 这将主要取决于哪个线程首先命中yield语句。

我读到当前运行的线程在线程池中始终是相等或最高优先级的线程。 这个陈述是错的吗?

是的,这是错的。 实际上,Java语言规范或Java虚拟机规范都没有提到线程优先级。 java.lang.Thread的javadoc说(只)这个:

每个线程都有优先权。 具有较高优先级的线程优先于具有较低优先级的线程执行。

事实上,Java的线程优先级模型是未指定的,并且线程优先级的影响是JVM,硬件和应用程序特定的。 您的陈述(上述)可能不正确的一些原因如下:

  • 如果JVM使用多个处理器,您可以合理地期望高优先级和低优先级线程同时运行。

  • 如果唯一的高优先级线程调用yield() ,则优先级较低的线程将开始运行。

  • 如果高优先级线程在I / O调用中阻塞,则可能无法在I / O完成时立即恢复。

  • 一些JVM实现了时间分片,并且当唯一的高优先级线程的时间滑动完成时,可能会安排低优先级线程运行。 (实际上,我不知道这是否会发生……但可以说这样做是为了减轻“优先倒置”问题是一件好事。)

在实践中,这意味着您不应该依赖优先级来为您提供精细的调度; 例如,通过上下调整优先级。 而且你当然不应该使用优先级来代替正确的同步。