1

我正在尝试创建具有一定数量线程的 ThreadPoolExecutor,但同时,我想控制池队列的大小。所以我使用完整的构造函数创建了执行器:

 BlockingQueue<Runnable> pq =
     new ArrayBlockingQueue<Runnable>(MAX_THREADPOOL_SIZE);
 ThreadPoolExecutor threadPoolExecutor =
     new ThreadPoolExecutor(threadSize, threadSize, THREAD_IDLE_WAIT,
          TimeUnit.SECONDS, pq);

但是,这给了我一个IllegalArgumentException. 如果我将构造函数更改为

new ThreadPoolExecutor(threadSize, **threadSize+1**, THREAD_IDLE_WAIT,
     TimeUnit.SECONDS, pq);

有用。如果我希望理想的线程数和最大线程数相同,为什么它不起作用。

4

3 回答 3

4

来自javadoc:如果 corePoolSize 或 keepAliveTime 小于零,或者如果 maximumPoolSize 小于或等于零,或者如果corePoolSize 大于 maximumPoolSize。所以它们也可以相等。我也尝试过用相等的值构造并且它有效。也许源代码可以帮助您找出问题所在:

if (corePoolSize < 0 ||
    maximumPoolSize <= 0 ||
    maximumPoolSize < corePoolSize ||
    keepAliveTime < 0)
    throw new IllegalArgumentException();
于 2012-08-09T16:48:49.850 回答
0

我看不出你的初始代码应该抛出的原因。如果您将来提供完整的例外情况,我们可以提供更具体的帮助。

要记住的一件事是,BlockingQueue一旦队列已满,使用有界将引发异常。这很少是你所期望的。如果您看一下我对以下问题的回答,您会发现您需要配置一个RejectedExecutionHandler

如果需要处理的数据太多,如何让 ThreadPoolExecutor 命令等待?

要从那里复制,您需要执行以下操作:

final BlockingQueue queue = new ArrayBlockingQueue<Runnable>(200);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(nThreads, nThreads,
           0L, TimeUnit.MILLISECONDS, queue);
// by default (unfortunately) the ThreadPoolExecutor will throw an exception
// when you submit the 201st job, to have it block you do:
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
   public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
      // this will block if the queue is full
      executor.getQueue().put(r);
   }
});

最后,如果您的最大线程大小大于核心线程大小,您必须意识到队列将在分配超过核心大小的任何其他线程之前填满。奇怪但真实。

于 2012-08-09T18:07:10.090 回答
-1

改为使用工厂方法来获取恒定数量的线程。

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int )

然后根据需要设置超时。

ThreadPoolExecutor exec = (ThreadPoolExecutor)Executors.newFixedThreadPool(threadSize);
exec.setKeepAliveTime(THREAD_IDLE_WAIT, TimeUnit.SECONDS);
于 2012-08-09T16:37:21.777 回答