【问题标题】:In Java 6, why doesn't higher priority thread not run even if lower priority thread yields?在 Java 6 中,为什么即使低优先级线程产生,高优先级线程也不会运行?
【发布时间】:2009-12-28 20:36:48
【问题描述】:

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

import java.util.ArrayList;
import java.util.List;

public class TestThreadPriority extends Thread {

    static List<String> messages = new ArrayList<String>();

    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

非常感谢任何帮助。

谢谢, 方格

【问题讨论】:

标签: java multithreading


【解决方案1】:

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

您的代码的另一个问题是您在没有同步的情况下从多个线程访问messages

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

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

【讨论】:

  • +1 - 打败我。对于一些运行时间较长的代码,他可能会看到不同。
  • 谢谢马克,这解释了很多。我读到当前正在运行的线程始终是线程池中相同或最高优先级的线程。这个说法有错吗?
  • 这听起来不对,你在哪里读到的?有链接吗?
  • 我阅读了 SCJP 6 学习指南。但现在我知道这是错的。
【解决方案2】:

我读到当前正在运行的线程总是线程池中相同或最高优先级的线程。这个说法有错吗?

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

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

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

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

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

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

  • 一些 JVM 实现了时间片,当唯一的高优先级线程的时间滑动完成时,可能会调度低优先级线程运行。 (实际上,我不知道这是否会发生……但可以说,这样做可以缓解“优先级倒置”问题。)

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

【讨论】:

    猜你喜欢
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 2011-06-25
    • 2014-10-27
    • 2013-02-11
    相关资源
    最近更新 更多