限制缓存线程池的创建数量似乎是不可能的。
这是在标准Java库中实现static Executors.newCachedThreadPool的方式:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
因此,使用该模板继续创建固定大小的缓存线程池:
new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronusQueue<Runable>());
现在,如果您使用它并提交3个任务,一切都会好起来的。提交任何其他任务将导致拒绝执行异常。
试试这个:
new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runable>());
将导致所有线程按顺序执行。即,线程池将永远不会产生多个线程来处理您的任务。
这是ThreadPoolExecutor的execute方法中的错误吗?还是这是故意的?还是有其他方法?
编辑:我想要的东西完全类似于缓存的线程池(它会按需创建线程,然后在超时后将其杀死),但是它可以创建的线程数受到限制,并且一旦有线程就可以继续排队其他任务达到其线程限制。根据sjlee的答复,这是不可能的。查看ThreadPoolExecutor的execute()方法确实是不可能的。我需要像SwingWorker一样子类化ThreadPoolExecutor并重写execute(),但是SwingWorker在execute()中所做的事情是一个完整的技巧。
ThreadPoolExecutor具有以下几种关键行为,这些问题可以解释您的问题。
提交任务后,
在第一个示例中,请注意,SynchronousQueue本质上的大小为0。因此,当您达到最大大小(3)时,拒绝策略开始执行(#4)。
在第二个示例中,选择的队列是LinkedBlockingQueue,它的大小不受限制。因此,您将陷入行为2。
您实际上不能对缓存类型或固定类型进行太多修改,因为它们的行为几乎完全确定了。
如果要有一个有限的动态线程池,则需要使用正的核心大小和最大大小以及有限大小的队列。例如,
new ThreadPoolExecutor(10, // core size
50, // max size
10*60, // idle timeout
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(20)); // queue with a size
附录:这是一个相当老的答案,并且看起来JDK更改了其行为,即核心大小为0。从JDK 1.6开始,如果核心大小为0并且该池没有任何线程,则ThreadPoolExecutor将添加一个执行该任务的线程。因此,核心大小0是上述规则的例外。感谢史蒂夫为使这引起我的注意。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句