简体   繁体   中英

ThreadPoolExecutor limited number of threads

I'm trying to create a ThreadPoolExecutor with a certain number of threads, but at the same time, i want to control the size of the pool queue. So I created the executor using the full constructor:

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

However, this gives me an IllegalArgumentException . If I change the constructor to

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

it works. Why won't it work if I want the ideal and max amount of threads to be the same.

From javadoc : if corePoolSize, or keepAliveTime less than zero, or if maximumPoolSize less than or equal to zero, or if corePoolSize greater than maximumPoolSize . So they can also be equal. I have also tried constructing with equal values and it works. Maybe the source code can help you find out what the problem is:

if (corePoolSize < 0 ||
    maximumPoolSize <= 0 ||
    maximumPoolSize < corePoolSize ||
    keepAliveTime < 0)
    throw new IllegalArgumentException();

I see no reason why your initial code should have thrown. If you provide the full exception in the future, we can provide more specific help.

One thing to remember is that using a bounded BlockingQueue will throw an exception once the queue is full. This is rarely what you'd expect. If you take a look at my answer to the following question, you will see that you need to configure a RejectedExecutionHandler :

How can I make ThreadPoolExecutor command wait if there's too much data it needs to work on?

To copy from there, you need to do something like the following:

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);
   }
});

Lastly, if your max-thread size is greater than the core-thread size, you must realize that the queue will fill before any additional threads over the core-size are allocated. Strange but true.

Use the factory method for a constant number of threads instead.

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

Then set your timeout however you need.

ThreadPoolExecutor exec = (ThreadPoolExecutor)Executors.newFixedThreadPool(threadSize);
exec.setKeepAliveTime(THREAD_IDLE_WAIT, TimeUnit.SECONDS);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM