将线程优先级传递给线程池

时间:2010-12-30 08:01:13

标签: java multithreading

我有一个Java组件,它执行一些超级复杂的业务逻辑,其中一些并行化,并且执行子任务的线程被合并。现在,对此组件的每个请求都可以具有某些优先级,这些优先级以某种方式映射到线程优先级。在执行的开始,我可以为执行线程分配适当的优先级。有问题的部分是将优先级传递给执行子任务的每个线程。我知道产生一个新的子线程会实现这一点,因为子线程继承了父线程的优先级,但我想利用线程池。一个问题:

  • 有没有办法确保执行路径中的每个线程都有适当的优先级?
  • 如何在每个执行阶段监控线程优先级,当然我不想对任何跟踪代码进行硬编码?我想到的是在BTrace
  • 中写一些跟踪脚本

干杯。 托梅克

5 个答案:

答案 0 :(得分:4)

我假设你已经知道这一点,但是JDK Thread的优先级值是否重要是高度特定于操作系统的,并且可能转化为“无论如何都没有效果”。所以你确定它真的很重要吗?如果是这样,可能编辑问题提及系统运行的操作系统。

另外:即使尝试使用线程优先级也不常见;除了优先事项不一定有效之外,即使它们有效,也要充分利用它们并非易事。更常见的是使用同步原语,以及控制并发级别(活动线程数),而不是优先级。这是因为拥有比核心系统更多的活动CPU边界线​​程很少有好处。

答案 1 :(得分:4)

您希望使用线程池,如果您只是为了设置作业优先级而必须生成新线程,这将变得毫无用处。

我认为您希望每个作业(不是线程)具有不同的优先级。如果是这种情况,让我们看一下ThreadPoolExecutor的构造函数签名:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue)
  • 不使用推荐的Executors'工厂方法之一来构建线程池,而是使用众多签名之一自己new ThreadPoolExecutor(...)
  • Executors.defaultThreadFactory传递给此构造函数(上面列出的签名在内部执行此操作)。这将执行自动线程优先级分配,因为它创建线程(对于固定大小的线程池,每个线程应该只在应用程序启动时发生一次)。
  • BlockingQueue<Runnable>PriorityBlockingQueue<Runnable>传递给此构造函数。这是一个队列,允许您优先处理作业(而不是线程)。
  • Runnable扩展为允许获取/设置优先级的抽象PriorityRunnable类。这些代表作业,因此当您想要创建新作业时,只需对其进行扩展并根据该作业自定义优先级。
  • 实施Comparator以在将元素插入队列时对元素执行排序,并让该队列使用它。
  • 将您的作业添加到队列中。

请注意,如果此时已填充您的队列(例如批量处理应用),您可以在构建后立即致电executor.prestartAllCoreThreads()executor.prestartCoreThread(n)

这一切都非常简单,只需要很少的代码就可以设置。

编辑:刚刚发现了正在讨论的相同方法over at Java Ranch

答案 2 :(得分:3)

就设置线程的优先级而言,您可以使用带有ThreadFactory的Executors类的不同方法。该工厂将负责根据传入的“Runnable”创建线程。

关于监控,当您说“执行的每个阶段”时,您是否可以根据此处尝试解决的方案进行推断?由于在其他地方已经mentioned,因为Java和OS线程优先级之间没有明确的映射,依赖于这些优先级将是一件坏事,如果这是你在这里尝试的。

答案 3 :(得分:2)

我最近实现了这个。尼克威吉尔建议,我做得很多。

但是你不能只做他建议的事情,因为ThreadPoolExecutor不会把你要求的工作放在workQueue中 - 相反,它将它们包装在自己的RunnableFuture中并将它们放入队列中。因此,您必须覆盖其newTaskFor方法以传递优先级。

源代码在Apache 2.0许可下在线: https://github.com/TheClimateCorporation/claypoole/blob/master/src/java/com/climate/claypoole/impl/PriorityThreadpoolImpl.java

答案 4 :(得分:1)

这可以解决您的问题:Thread.currentThread()。setPriority([1..5]);

您可以随时随地使用它们。如果在线程池启动的runnable中使用它们,则可以控制单线程优先级并根据需要进行更改。