具有有限线程数的执行程序

时间:2013-07-30 05:38:15

标签: java java.util.concurrent threadpoolexecutor

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

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

// taken from Executors.newFixedThreadPool()
new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());

所以我尝试用这种方式创建ExecutorService

// taken from Executors.newCachedThreadPool()
new ThreadPoolExecutor(0, nThreads,
    CACHED_POOL_SHUTDOWN_DELAY, TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>());

但是,当nThreads正在使用时,Executor不会按预期运行,RejectedExecutionException不会将新任务排入队列,但会抛出Executor。我知道我可以为此实现一个处理程序,但它对我没有帮助。

如何创建前面描述的{{1}}?

2 个答案:

答案 0 :(得分:1)

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

它适用于CachedThreadPool,因为最大核心池大小很大(Integer.MAX_VALUE)。

您需要使用不同的队列,例如固定线程池示例中的新LinkedBlockingQueue

附注:检查实施文档有助于了解详细信息。特别是,execute类的ThreadPoolExecutor方法具有:

   /*
     * 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.
     */

答案 1 :(得分:1)

我在that post找到了一种方法,完全符合我的需要 @assylias我认出你的答案并改变了队列实施。

现在我的代码看起来像这样:

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

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

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