2013-07-30 21 views
0

我在寻找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

我发现了一个方法上that post但这正是我所需要的。
@assylias我认出你的答案,并改变了队列的实施。

现在我的代码如下所示:

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

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

它就像一个固定的线程池,但这些核心这就是被允许的时间了。

1

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

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

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

备注:检查实施文档可帮助您了解详细信息。特别是,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. 
    */ 
+0

谢谢,你说得对。但可能会发生成千上万的排队队列,我不想创建如此庞大的队列。 – Stephan

+0

@Stephan您需要对无法运行的任务(使用最大池大小)进行操作并且无法入队(队列已满)...您可以限制队列的大小,但您将收到一旦它已满,就会发生异常。 – assylias

+1

这是真的。我从队列的构造函数中删除了'capacity'参数,因此它被设置为'Integer.MAX_VALUE'。 – Stephan