java将线程优先级传递给线程池
我有一个Java组件,它执行一些超复杂的业务逻辑,其中一些是并行的,执行子任务的线程是池化的。现在,对这个组件的每个请求都可以有一些优先级,这些优先级以某种方式映射到线程优先级。在执行开始时,我可以为执行线程分配适当的优先级。问题在于将优先级传递给执行子任务的每个线程。我知道产生一个新的子线程将实现这一点,因为子线程继承父线程的优先级,但我想利用线程池。问题的答案是:
- 有没有办法确保执行路径中的每个线程都有适当的优先级李>
- 我如何在执行的每个阶段监控线程优先级,当然我不想硬编码任何跟踪代码?我想到的一件事是在BTrace中写一些跟踪脚本
干杯。 托梅克
# 1 楼答案
您希望使用线程池,如果您必须生成新线程来设置作业优先级,那么线程池将变得无用
我认为您希望每个作业(而不是线程)具有不同的优先级。如果是这种情况,让我们看看
ThreadPoolExecutor
的构造函数签名:Executors
工厂方法来构建线程池,而是使用它的众多签名中的一个,自己动手new ThreadPoolExecutor(...)
李>Executors.defaultThreadFactory
传递到这个构造函数中(上面列出的签名在内部执行此操作)。这将在创建线程时自动执行线程优先级分配(对于固定大小的线程池,在应用程序启动时,每个线程只应执行一次)李>BlockingQueue<Runnable>
或PriorityBlockingQueue<Runnable>
传递到此构造函数。这是一个队列,允许您对作业进行优先级排序(而不是线程)李>Runnable
扩展为一个抽象的PriorityRunnable
类,该类允许获取/设置优先级。它们代表了作业,因此当你想做一个新作业时,只需扩展它,并根据该作业的情况自定义设置优先级李>Comparator
在将元素插入队列时对元素执行排序,并让该队列使用它李>请注意,如果此时已经填充了队列(例如,对于批处理应用程序),则可以在构建后立即调用
executor.prestartAllCoreThreads()
或executor.prestartCoreThread(n)
这一切都非常简单,而且只需要几行代码就可以完成
编辑:刚刚发现同样的方法正在讨论over at Java Ranch
# 2 楼答案
我最近实现了这个。我按照尼克·威吉尔的建议做了
但你不能照他的建议去做,因为ThreadPoolExecutor不会将你要求的作业放入工作队列——相反,它会将它们包装在自己的RunnableFuture中,并将它们放入队列中。所以你必须重写它的newTaskFor方法来传递优先级
源代码在Apache 2.0许可下在线: https://github.com/TheClimateCorporation/claypoole/blob/master/src/java/com/climate/claypoole/impl/PriorityThreadpoolImpl.java
# 3 楼答案
就设置线程的优先级而言,可以使用Executors类的不同方法,这些方法采用ThreadFactory。该工厂将负责根据传入的“Runnable”创建线程
关于监控,当你说“执行的每个阶段”时,你能推断出你试图解决的场景吗?正如其他地方一样,由于Java和OS线程优先级之间没有明确的映射关系,依赖这些优先级将是一件坏事,如果您在这里尝试的是这样的话
# 4 楼答案
这可以解决你的问题:线程。currentThread()。设置优先级([1..5])
你可以在任何地方使用它们。如果从线程池启动的runnable中使用它们,则可以控制单线程优先级,并根据需要进行更改
# 5 楼答案
我想你已经知道了这一点,但JDK线程的优先级值是否重要是高度特定于操作系统的,可能会转化为“没有任何影响”。你确定这真的很重要吗?如果是这样的话,也许可以编辑问题,提及系统运行的操作系统
另外:甚至尝试使用线程优先级也不是很常见;除了不一定有效的优先事项之外,即使它们有效,也要充分利用它们。更常见的是使用同步原语,以及控制并发级别(活动线程的数量),而不是优先级。这是因为拥有比系统内核更多的活动CPU边界线程很少有好处