Creating a dynamic (growing/shrinking) thread pool

混江龙づ霸主 提交于 2019-12-02 22:57:29
Gray

One trick that might help you is to assign a RejectedExecutionHandler that uses the same thread to submit the job into the blocking queue. That will block the current thread and remove the need for some sort of loop.

See my answer here:

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

Here's the rejection handler copied from that answer.

final BlockingQueue queue = new ArrayBlockingQueue<Runnable>(200);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(nThreads, nThreads,
       0L, TimeUnit.MILLISECONDS, queue);
// by default (unfortunately) the ThreadPoolExecutor will call the rejected
// handler 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);
   }
});

You should then be able to make use of the core/max thread count as long as you realize that the bounded blocking queue that you use first fills up before any threads are created above the core threads. So if you have 10 core threads and you want the 11th job to start the 11th thread you will need to have a blocking queue with a size of 0 unfortunately (maybe a SynchronousQueue). I feel that this is a real limitation in the otherwise great ExecutorService classes.

Kumar Vivek Mitra

When growing and shrinking comes together with thread, there is only one name which comes to my mind: CachedThreadPool from java.util.concurrent package.

ExecutorService executor = Executors.newCachedThreadPool();

CachedThreadPool() can reuse the thread, as well as create new threads when needed. And yes, if a thread is idle for 60 seconds, CachedThreadPool will kill it. So this is quite lightweight – growing and shrinking in your words!

Set maximumPoolSize to Integer.MAX_VALUE. If you ever have more than 2 billion threads...well, good luck with that.

Anyway, the Javadoc of ThreadPoolExecutor states:

By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks. Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using setCorePoolSize(int) and setMaximumPoolSize(int).

With a similarly unbounded task queue like a LinkedBlockingQueue, this should have arbitrarily large capacity.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!