【问题标题】:Passing thread priorities to thread pools将线程优先级传递给线程池
【发布时间】:2011-06-01 10:50:31
【问题描述】:

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

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

干杯。 托梅克

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    我最近实现了这个。我按照 Nick Wiggill 的建议做了很多事情。

    但是你不能只是按照他的建议去做,因为 ThreadPoolExecutor 不会将你要求的作业放入 workQueue 中——而是将它们包装在自己的 RunnableFuture 中并将它们放入队列中。所以你必须重写它的 newTaskFor 方法来传递优先级。

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

    【讨论】:

      【解决方案2】:

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

      我认为您希望每个 job(而不是 thread)具有不同的优先级。如果是这样,让我们​​看看ThreadPoolExecutor 的构造函数签名:

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

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

      这一切都非常简单,只需几行代码即可设置。

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

      【讨论】:

        【解决方案3】:

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

        您可以在任何地方使用它们。如果您从线程池启动的可运行对象内部使用它们,您可以控制单个线程的优先级并根据需要进行更改。

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

          • 我知道优先级的实现是一个非常特定于操作系统/JVM 的想法,但我的组件只在窗口上工作,优先级似乎在那里工作得很好。此外,我不是从头开始构建组件,而只是将优先级插入现有事物中。您提到了同步原语。您能否详细说明一下,您将如何使用这种方法来确定 1000 个并行请求的优先级,而不会使优先级最低的请求挨饿?
          • 写入 1k 请求;要看。如果他们大部分时间都在等待 I/O,那么使用 NIO(基于解决方案)将是有意义的——1000 个或更多线程可能是非常低效的模型。如果 CPU 受限,那么,IMO 你不应该开始服务那么多并发请求,而是尽早开始失败。所以我的意思是通过排队限制实际线程的数量,提前开始失败等:线程无法解决过载情况。但是如果你觉得线程优先级有帮助,并且它们确实在平台上工作(你可能对 wrt Windows 是正确的),那么使用没有错。只是确保他们提供帮助。
          【解决方案5】:

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

          关于监控,当您说“执行的每个阶段”时,您能否推断您在此处尝试解决的场景?就像其他地方的 mentioned 一样,由于 Java 和 OS 线程优先级之间没有明确的映射,因此依赖这些优先级将是一件坏事,以防您在这里尝试这样做。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-06-25
            • 1970-01-01
            • 2023-04-09
            • 2012-11-17
            • 2016-06-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多