Java线程池执行器策略&x27;直接切换';排队?

Java线程池执行器策略&x27;直接切换';排队?,java,threadpool,Java,Threadpool,我希望有一个ThreadPoolExecutor,在这里我可以设置corePoolSize和maximumPoolSize,然后队列会立即将任务转移到线程池,从而创建新线程,直到它达到maximumPoolSize,然后开始添加到队列中 有这样的事吗?如果没有,有什么好的理由没有这样的策略吗 本质上,我想要的是任务被提交执行,当它达到一个临界点时,由于线程太多(通过设置maximumPoolSize),它会停止添加新线程,使用线程池并开始排队,如果队列已满,它会拒绝 当负载下降时,它可以开始将未

我希望有一个
ThreadPoolExecutor
,在这里我可以设置
corePoolSize
maximumPoolSize
,然后队列会立即将任务转移到线程池,从而创建新线程,直到它达到
maximumPoolSize
,然后开始添加到队列中

有这样的事吗?如果没有,有什么好的理由没有这样的策略吗

本质上,我想要的是任务被提交执行,当它达到一个临界点时,由于线程太多(通过设置maximumPoolSize),它会停止添加新线程,使用线程池并开始排队,如果队列已满,它会拒绝

当负载下降时,它可以开始将未使用的线程分解回corePoolSize


在我的应用程序中,这比

中列出的“三个一般策略”更有意义。注意:这些实现有些缺陷,而且不确定。使用此代码前,请阅读完整答案和注释。

创建一个工作队列,在执行器低于最大池大小时拒绝项目,并在达到最大池大小后开始接受项目,怎么样

这取决于记录的行为:

如果请求无法排队,则会创建一个新线程,除非 将超过maximumPoolSize,在这种情况下,任务将 拒绝。”


我们通过以下代码找到了该问题的解决方案:

此队列是SynchronousQueue/LinkedBlockingQueue的混合

public class OverflowingSynchronousQueue<E> extends LinkedBlockingQueue<E> {
  private static final long serialVersionUID = 1L;

  private SynchronousQueue<E> synchronousQueue = new SynchronousQueue<E>();

  public OverflowingSynchronousQueue() {
    super();
  }

  public OverflowingSynchronousQueue(int capacity) {
    super(capacity);
  }

  @Override
  public boolean offer(E e) {
    // Create a new thread or wake an idled thread
    return synchronousQueue.offer(e);
  }

  public boolean offerToOverflowingQueue(E e) {
    // Add to queue
    return super.offer(e);
  }

  @Override
  public E take() throws InterruptedException {
    // Return tasks from queue, if any, without blocking
    E task = super.poll();
    if (task != null) {
      return task;
    } else {
      // Block on the SynchronousQueue take
      return synchronousQueue.take();
    }
  }

  @Override
  public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    // Return tasks from queue, if any, without blocking
    E task = super.poll();
    if (task != null) {
      return task;
    } else {
      // Block on the SynchronousQueue poll
      return synchronousQueue.poll(timeout, unit);
    }
  }
公共类溢出同步队列扩展LinkedBlockingQueue{
私有静态最终长serialVersionUID=1L;
private SynchronousQueue SynchronousQueue=新的SynchronousQueue();
公共溢出同步队列(){
超级();
}
公共溢出同步队列(int容量){
超级(容量);
}
@凌驾
公共布尔报价(E){
//创建新线程或唤醒空闲线程
返回synchronousQueue.offer(e);
}
公共布尔型offerToOverflowingQueue(E){
//添加到队列
返回超级报价(e);
}
@凌驾
public E take()抛出InterruptedException{
//从队列返回任务(如果有),不阻塞
E task=super.poll();
如果(任务!=null){
返回任务;
}否则{
//同步队列上的块
返回synchronousQueue.take();
}
}
@凌驾
公共E轮询(长超时,时间单位)抛出InterruptedException{
//从队列返回任务(如果有),不阻塞
E task=super.poll();
如果(任务!=null){
返回任务;
}否则{
//阻止SynchronousQueue轮询
返回synchronousQueue.poll(超时,单位);
}
}
}

为了让它工作,我们需要包装RejectedExecutionHandler,以便在任务被拒绝时调用“OfferToOverflowQueue”

public class OverflowingRejectionPolicyAdapter implements RejectedExecutionHandler {

  private OverflowingSynchronousQueue<Runnable> queue;
  private RejectedExecutionHandler adaptedRejectedExecutionHandler;

  public OverflowingRejectionPolicyAdapter(OverflowingSynchronousQueue<Runnable> queue,
                                           RejectedExecutionHandler adaptedRejectedExecutionHandler)
  {
    super();
    this.queue = queue;
    this.adaptedRejectedExecutionHandler = adaptedRejectedExecutionHandler;
  }

  @Override
  public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    if (!queue.offerToOverflowingQueue(r)) {
      adaptedRejectedExecutionHandler.rejectedExecution(r, executor);
    }
  }
}
公共类溢出RejectionPolicyAdapter实现RejectedExecutionHandler{
私有溢出同步队列;
私有RejectedExecutionHandler adaptedRejectedExecutionHandler;
公共溢出拒绝策略适配器(溢出同步队列,
RejectedExecutionHandler adaptedRejectedExecutionHandler)
{
超级();
this.queue=队列;
this.adaptedRejectedExecutionHandler=adaptedRejectedExecutionHandler;
}
@凌驾
public void rejectedExecution(可运行的r、线程池执行器执行器){
if(!queue.offerToOverflowingQueue(r)){
adaptedRejectedExecutionHandler.rejectedExecution(r,执行者);
}
}
}
下面是我们如何创建ThreadPoolExecutor的

public static ExecutorService newSaturatingThreadPool(int corePoolSize,
                                                        int maxPoolSize,
                                                        int maxQueueSize,
                                                        long keepAliveTime,
                                                        TimeUnit timeUnit,
                                                        String threadNamePrefix,
                                                        RejectedExecutionHandler rejectedExecutionHandler)
  {
  OverflowingSynchronousQueue<Runnable> queue = new OverflowingSynchronousQueue<Runnable>(maxQueueSize);
  OverflowingRejectionPolicyAdapter rejectionPolicyAdapter = new OverflowingRejectionPolicyAdapter(queue,
                                                                                                     rejectedExecutionHandler);
  ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize,
                                                         maxPoolSize,
                                                         keepAliveTime,
                                                         timeUnit,
                                                         queue,
                                                         new NamedThreadFactory(threadNamePrefix),
                                                         rejectionPolicyAdapter);
  return executor;
}
publicstaticexecutorservice newSaturatingThreadPool(int-corePoolSize,
int maxPoolSize,
int maxQueueSize,
长时间,
时间单位时间单位,
字符串threadNamePrefix,
RejectedExecutionHandler RejectedExecutionHandler)
{
OverflowingSynchronousQueue=新的OverflowingSynchronousQueue(maxQueueSize);
OverflowInRejectionPolicyAdapter rejectionPolicyAdapter=新的OverflowInRejectionPolicyAdapter(队列,
拒绝执行处理程序);
ThreadPoolExecutor executor=新的ThreadPoolExecutor(corePoolSize,
最大池大小,
守时,
时间单位,
队列
新命名的ThreadFactory(threadNamePrefix),
拒绝策略适配器);
返还执行人;
}

您的建议是我在现已删除的答案的评论中所说的。无论如何我想你会发现,压倒一切的报价可能会导致问题,因为它没有锁。即使只有3条指令?“或者这么长时间了。”我也在关注同样的事情,我一直试图通过推理解决潜在的问题,但我还没有找到任何答案。我会继续努力仔细考虑。无论如何,接受你的答案。这就是我最后实现的,而不是试图重写ThreadPoolExecutor的执行方法,后者要复杂得多。仅供参考,我还将maximumPoolSize中的缓冲区添加到比实际值低5%的位置,以允许比赛。不是理想的方法,而是Threa的默认行为
public class OverflowingRejectionPolicyAdapter implements RejectedExecutionHandler {

  private OverflowingSynchronousQueue<Runnable> queue;
  private RejectedExecutionHandler adaptedRejectedExecutionHandler;

  public OverflowingRejectionPolicyAdapter(OverflowingSynchronousQueue<Runnable> queue,
                                           RejectedExecutionHandler adaptedRejectedExecutionHandler)
  {
    super();
    this.queue = queue;
    this.adaptedRejectedExecutionHandler = adaptedRejectedExecutionHandler;
  }

  @Override
  public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    if (!queue.offerToOverflowingQueue(r)) {
      adaptedRejectedExecutionHandler.rejectedExecution(r, executor);
    }
  }
}
public static ExecutorService newSaturatingThreadPool(int corePoolSize,
                                                        int maxPoolSize,
                                                        int maxQueueSize,
                                                        long keepAliveTime,
                                                        TimeUnit timeUnit,
                                                        String threadNamePrefix,
                                                        RejectedExecutionHandler rejectedExecutionHandler)
  {
  OverflowingSynchronousQueue<Runnable> queue = new OverflowingSynchronousQueue<Runnable>(maxQueueSize);
  OverflowingRejectionPolicyAdapter rejectionPolicyAdapter = new OverflowingRejectionPolicyAdapter(queue,
                                                                                                     rejectedExecutionHandler);
  ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize,
                                                         maxPoolSize,
                                                         keepAliveTime,
                                                         timeUnit,
                                                         queue,
                                                         new NamedThreadFactory(threadNamePrefix),
                                                         rejectionPolicyAdapter);
  return executor;
}