Mat*_*ogt 118 java concurrency multithreading executorservice threadpoolexecutor
似乎不可能创建一个缓存的线程池,它可以创建的线程数限制.
以下是在标准Java库中实现静态Executors.newCachedThreadPool的方法:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
Run Code Online (Sandbox Code Playgroud)
因此,使用该模板继续创建固定大小的缓存线程池:
new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronusQueue<Runable>());
Run Code Online (Sandbox Code Playgroud)
现在,如果你使用它并提交3个任务,一切都会好的.提交任何进一步的任务将导致被拒绝的执行异常.
试试这个:
new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runable>());
Run Code Online (Sandbox Code Playgroud)
将导致所有线程按顺序执行.即,线程池永远不会有多个线程来处理您的任务.
这是ThreadPoolExecutor的execute方法中的错误?或者这可能是故意的?还是有其他方式?
编辑:我想要一些与缓存线程池完全相同的东西(它根据需要创建线程,然后在一些超时后杀死它们)但是它可以创建的线程数量受到限制,并且一旦有了它就能够继续排队其他任务达到了它的线程限制.根据sjlee的回应,这是不可能的.查看ThreadPoolExecutor的execute()方法确实是不可能的.我需要继承ThreadPoolExecutor并覆盖execute(),就像SwingWorker一样,但SwingWorker在其execute()中所做的是一个完整的hack.
sjl*_*lee 226
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
Run Code Online (Sandbox Code Playgroud)
附录:这是一个相当陈旧的答案,看来JDK在核心大小为0时改变了它的行为.从JDK 1.6开始,如果核心大小为0且池没有任何线程,则ThreadPoolExecutor将添加一个线程来执行该任务.因此,核心大小为0是上述规则的例外.感谢史蒂夫为使这引起我的注意.
小智 59
除非我错过了什么,否则原始问题的解决方案很简单.以下代码实现了原始海报所描述的所需行为.它将产生最多5个线程来处理无界队列,空闲线程将在60秒后终止.
tp = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
tp.allowCoreThreadTimeOut(true);
Run Code Online (Sandbox Code Playgroud)
有同样的问题.由于没有其他答案将所有问题放在一起,我加入我的:
它现在清楚地写在文档中:如果使用不阻塞的队列(LinkedBlockingQueue)最大线程设置没有效果,则只使用核心线程.
所以:
public class MyExecutor extends ThreadPoolExecutor {
public MyExecutor() {
super(4, 4, 5,TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
allowCoreThreadTimeOut(true);
}
public void setThreads(int n){
setMaximumPoolSize(Math.max(1, n));
setCorePoolSize(Math.max(1, n));
}
}
Run Code Online (Sandbox Code Playgroud)
该执行人具有:
没有最大线程的概念,因为我们正在使用无界队列.这是一件好事,因为这样的队列可能会导致执行程序创建大量非核心额外线程,如果它遵循其通常的策略.
最大大小的队列Integer.MAX_VALUE.如果待处理任务的数量超过,Submit()则会抛出.不确定我们会先耗尽内存还是会发生这种情况.RejectedExecutionExceptionInteger.MAX_VALUE
有4个核心线程可能.闲置核心线程如果空闲5秒则自动退出.所以,是的,严格按需求threads.Number可以使用setThreads()方法改变.
确保最小数量的核心线程永远不会少于一个,否则submit()将拒绝每个任务.由于核心线程需要> = max个线程,因此该方法也setThreads()设置了最大线程,尽管最大线程设置对于无界队列是无用的.
在第一个示例中,后续任务被拒绝,因为它AbortPolicy是默认任务RejectedExecutionHandler.ThreadPoolExecutor包含以下策略,您可以通过以下setRejectedExecutionHandler方法更改这些策略:
CallerRunsPolicy
AbortPolicy
DiscardPolicy
DiscardOldestPolicy
Run Code Online (Sandbox Code Playgroud)
听起来你想要一个CallerRunsPolicy的缓存线程池.
小智 5
这里的答案都没有解决我的问题,这与使用Apache的HTTP客户端(3.x版本)创建有限数量的HTTP连接有关.由于我花了几个小时来找出一个好的设置,我将分享:
private ExecutorService executor = new ThreadPoolExecutor(5, 10, 60L,
TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
Run Code Online (Sandbox Code Playgroud)
这将创建一个ThreadPoolExecutor以5开头并最多使用10个同时运行的线程来CallerRunsPolicy执行.
| 归档时间: |
|
| 查看次数: |
45396 次 |
| 最近记录: |