在下面的代码中,我试图通过产生优先级较低的线程来获得更高优先级的线程。但它似乎不起作用,优先级较低的线程似乎在较低优先级的线程完成后运行。谁能解释我做错了什么?
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
- 线程0:1
- 线程0:1
- 主:1
- 螺纹-1:10
- 螺纹-1:10
醇>
非常感谢任何帮助。
谢谢, 奎德
答案 0 :(得分:9)
我猜你的第一个线程甚至在第二个线程启动之前就已经完成了。也许如果你的线程做了一些真正的工作(或者甚至只是睡了一会儿),你会看到来自两个线程的重叠消息。
您的代码的另一个问题是您从多个线程访问messages
而未进行同步。
在尝试打印messages
的内容之前,您还应该加入已经启动的两个线程,以确保您启动的线程已经记录了他们的消息,并且他们不会尝试修改列表,当你迭代它打印它时。
一旦你解决了所有这些问题,最后一点就是两个你的线程正在屈服,而不仅仅是优先级较低的线程。当优先级较高的线程产生时,较低优先级的线程获得一些运行时间是完全合理的。拥有更高的优先权并不会给你带来垄断。在您的简化代码示例中,优先级可能不会对发生的情况产生太大影响 - 这将主要取决于哪个线程首先命中yield语句。
答案 1 :(得分:2)
我读到当前运行的线程在线程池中始终是相等或最高优先级的线程。这个陈述是错的吗?
是的,这是错的。实际上,Java语言规范或Java虚拟机规范都没有提到线程优先级。 java.lang.Thread
的javadoc说(仅)这个:
每个帖子都有优先权。优先级较高的线程优先于优先级较低的线程执行。
实际上Java的线程优先级模型是未指定的,并且线程优先级的影响是JVM,硬件和应用程序特定的。您的陈述(上文)可能不正确的一些原因如下:
如果JVM使用多个处理器,您可以合理地期望高优先级和低优先级线程同时运行。
如果唯一的高优先级线程调用yield()
,则优先级较低的线程将开始运行。
如果高优先级线程在I / O调用中阻塞,则可能无法在I / O完成时立即恢复。
某些JVM实现时间切片,并且可能可以在唯一的高优先级线程的时间滑动完成时调度低优先级线程。 (实际上,我不知道这是否会发生......但可以说这样做是为了减轻“优先倒置”问题是一件好事。)
在实践中,这意味着您不应该依赖优先级来为您提供细粒度的调度;例如通过上下调整优先级。你当然不应该使用优先级来代替正确的同步。