【问题标题】:ThreadPoolExecutor without a Queue没有队列的 ThreadPoolExecutor
【发布时间】:2012-04-17 06:42:05
【问题描述】:

我想创建一个固定大小的线程池,它不允许任何任务进入其队列。换句话说,如果线程池当前正在使用,那么传入的任务应该被彻底拒绝。基于documentation,在我看来,一种方法是创建一个拒绝承认任务的虚拟队列对象。在 Java 中实现这一点的惯用方法是什么?

【问题讨论】:

    标签: java queue threadpool


    【解决方案1】:

    您可以在 ThreadPoolExector 中使用SynchronousQueue,这是一个不包含任何对象的队列。缓存线程池使用它是因为它按需创建新线程。

    如果不能排队,但我建议使用RejectedExecutionHandler 在当前线程中运行任务。这样,它将始终“立即”运行。

    顺便说一句:说明你为什么要这样做会很有用。

    【讨论】:

    • 我们现在有一个用例。如果某个节点有一个空闲的worker,它可以接受新任务,否则其他一些节点会接受它,但任务不应该排队。如果排队,则没有机会获得另一个节点。
    【解决方案2】:

    我想创建一个固定大小的线程池,它不允许任何任务进入其队列。

    对于后代,如果您需要一个没有队列的线程池并且确实运行所有作业(与 OP 略有不同),那么您可以使用 SynchronousQueue 它将阻塞,直到线程准备好工作。诀窍是使用RejectedExecutionHandler 在将阻塞的队列上调用put(...)

    threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
      unit, new SynchronousQueue<Runnable>(),
      new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor){
          try {
            // this needs to be put(...) and not add(...)
            executor.getQueue().put(runnable);
          } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
          }
        }
      });
    

    在达到maximumPoolSize 线程数之前,您将能够提交作业,然后提交将阻塞,直到作业完成并且线程可以从SynchronousQueue 出队。

    【讨论】:

      【解决方案3】:

      你能详细说明你为什么要做这样的事情吗? TP + Q 的根本目的是为工作建立一个自动“持有机制”,并将工人与工作创建过程分离。如果您的意图是只拥有与工人一样多的可接受的工作包,那么您真的不需要 TPE。

      【讨论】:

      • 任务可以被另一个有空闲线程的线程池执行器拾取,而不是在前者的队列中等待。我应该使用什么来代替 ThreadPoolExecutor?
      • 如果您想控制执行,那么 TPE 不是您的选择。您最好拥有一个简单的工作线程集合,您可以将工作交给它们(如果它们可用)一个简单的 Set ,您可以构造并从主线程中拉入/推出线程。
      猜你喜欢
      • 1970-01-01
      • 2018-05-16
      • 2011-03-27
      • 2018-01-31
      • 2012-03-26
      • 2023-03-16
      • 1970-01-01
      • 2010-12-13
      • 1970-01-01
      相关资源
      最近更新 更多