Java 按需线程数有限的执行器

Java 按需线程数有限的执行器,java,java.util.concurrent,threadpoolexecutor,Java,Java.util.concurrent,Threadpoolexecutor,我正在寻找一个ExecutorService,它可以按需创建线程,达到预定义的限制,并在保持活动时间后销毁空闲线程 以下构造函数创建具有固定线程数的ThreadPoolExecutor: // taken from Executors.newFixedThreadPool() new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,

我正在寻找一个ExecutorService,它可以按需创建线程,达到预定义的限制,并在保持活动时间后销毁空闲线程

以下构造函数创建具有固定线程数的ThreadPoolExecutor:

// taken from Executors.newFixedThreadPool()
new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
但它并没有像预期的那样工作,当使用nThreads时,执行器不会将新任务排队,而是抛出一个RejectedExecutionException。我知道我可以为此实现一个处理程序,但它对我没有帮助


如何创建前面描述的执行器?

如果新任务无法排队,则会创建一个新线程,除非您已经达到最大核心池大小。在您的情况下,队列一次只能包含一个任务,因此如果您足够快地提交任务,您将达到最大池大小并获得异常

它与CachedThreadPool一起工作,因为最大核心池大小是大整数.MAX\u值

您需要使用不同的队列,例如新的LinkedBlockingQueue,如fixed threadpool示例中的

旁注:查看实现文档有助于理解细节。具体而言,ThreadPoolExecutor类的execute方法具有:

   /*
     * Proceed in 3 steps:
     *
     * 1. If fewer than corePoolSize threads are running, try to
     * start a new thread with the given command as its first
     * task.  The call to addWorker atomically checks runState and
     * workerCount, and so prevents false alarms that would add
     * threads when it shouldn't, by returning false.
     *
     * 2. If a task can be successfully queued, then we still need
     * to double-check whether we should have added a thread
     * (because existing ones died since last checking) or that
     * the pool shut down since entry into this method. So we
     * recheck state and if necessary roll back the enqueuing if
     * stopped, or start a new thread if there are none.
     *
     * 3. If we cannot queue task, then we try to add a new
     * thread.  If it fails, we know we are shut down or saturated
     * and so reject the task.
     */

如果新任务无法排队,则会创建一个新线程,除非您已经达到最大核心池大小。在您的情况下,队列一次只能包含一个任务,因此如果您足够快地提交任务,您将达到最大池大小并获得异常

它与CachedThreadPool一起工作,因为最大核心池大小是大整数.MAX\u值

您需要使用不同的队列,例如新的LinkedBlockingQueue,如fixed threadpool示例中的

旁注:查看实现文档有助于理解细节。具体而言,ThreadPoolExecutor类的execute方法具有:

   /*
     * Proceed in 3 steps:
     *
     * 1. If fewer than corePoolSize threads are running, try to
     * start a new thread with the given command as its first
     * task.  The call to addWorker atomically checks runState and
     * workerCount, and so prevents false alarms that would add
     * threads when it shouldn't, by returning false.
     *
     * 2. If a task can be successfully queued, then we still need
     * to double-check whether we should have added a thread
     * (because existing ones died since last checking) or that
     * the pool shut down since entry into this method. So we
     * recheck state and if necessary roll back the enqueuing if
     * stopped, or start a new thread if there are none.
     *
     * 3. If we cannot queue task, then we try to add a new
     * thread.  If it fails, we know we are shut down or saturated
     * and so reject the task.
     */
我找到了一种完全符合我需要的方法。 @assylias我认出了你的答案并更改了队列实现

现在,我的代码如下所示:

parallelExecutor = new ThreadPoolExecutor(nThreads, nThreads,
    CACHED_POOL_SHUTDOWN_DELAY, TimeUnit.SECONDS,
    new LinkedBlockingQueue<Runnable>());

parallelExecutor.allowCoreThreadTimeOut(true);   // this is the magic
它的工作原理类似于固定线程池,但这些核心允许超时。

我找到了一种方法,可以完全满足我的需要。 @assylias我认出了你的答案并更改了队列实现

现在,我的代码如下所示:

parallelExecutor = new ThreadPoolExecutor(nThreads, nThreads,
    CACHED_POOL_SHUTDOWN_DELAY, TimeUnit.SECONDS,
    new LinkedBlockingQueue<Runnable>());

parallelExecutor.allowCoreThreadTimeOut(true);   // this is the magic

它的工作原理类似于固定线程池,但这些核心允许超时。

谢谢,你说得对。但可能会发生这样的情况:数千个任务已排队,我不想创建这么大的队列。@Stephan您需要对无法运行的任务执行一些操作。使用了最大池大小,无法排队队列已满。。。您可以限制队列的大小,但一旦队列已满,您将收到异常。同样如此。我从队列的构造函数中删除了capacity参数,因此它被设置为Integer.MAX_VALUE。谢谢,你说得对。但可能会发生这样的情况:数千个任务已排队,我不想创建这么大的队列。@Stephan您需要对无法运行的任务执行一些操作。使用了最大池大小,无法排队队列已满。。。您可以限制队列的大小,但一旦队列已满,您将收到异常。同样如此。我从队列的构造函数中删除了capacity参数,因此它被设置为Integer.MAX\u VALUE。