我正在尝试创建一个具有一定数量线程的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);
它有效。如果我希望理想线程和最大线程数相同,为什么它不会工作。
答案 0 :(得分:4)
来自javadoc:如果corePoolSize或keepAliveTime小于零,或者maximumPoolSize小于或等于零,或者 corePoolSize大于maximumPoolSize 。所以他们也可以是平等的。我也尝试用相同的值构建它并且它有效。也许源代码可以帮助您找出问题所在:
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
答案 1 :(得分:0)
我认为你的初始代码没有理由抛出。如果您将来提供完整例外,我们可以提供更具体的帮助。
要记住的一件事是,一旦队列满了,使用有界BlockingQueue
将抛出异常。这很少是你所期望的。如果您查看我对以下问题的回答,您会看到需要配置RejectedExecutionHandler
:
How can I make ThreadPoolExecutor command wait if there's too much data it needs to work on?
要从那里复制,您需要执行以下操作:
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);
}
});
最后,如果你的最大线程大小大于核心线程大小,你必须意识到队列将在之前填充,然后分配核心大小的任何其他线程。奇怪但真实。
答案 2 :(得分:-1)
使用factory方法代替常量线程。
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);