我想在整个应用程序中使用相同的线程池。为此,我可以将ExecutorService
设置为静态和全局,这样我就可以在需要时调用ThreadUtil.executorService
来获取ExecutorService
。
public class ThreadUtil {
public static final ExecutorService executorService = Executors.newCachedThreadPool();
}
可以像这样实例化多个线程池吗?
另外,我的应用程序是TCP服务器。如果我不知道游泳池应该有多大,可以简单地使用newCachedThreadPool
吗?
答案 0 :(得分:4)
当在程序中的任何地方使用具有相同属性的实例时,将它声明为静态和最终而不是每次重新创建实例是合乎逻辑的,但我个人会选择Singleton模式而不是直接给出公共访问实例。
至于你的第二个查询,我认为没有任何问题。 newCachedThreadPool
文档的第一句话说
创建一个根据需要创建新线程的线程池
因为您不知道将创建多少个线程,所以这是最合理的选择。
请注意,newCachedThreadPool
会在可用于提高性能时重新使用旧线程。
答案 1 :(得分:0)
我不会直接全球化。至少将它包装在一个类中,这样您就可以轻松使用多个池。当您需要多种具有不同优先级的作业/作业时,拥有一个线程池池非常有用。只需在其他池和/或较低优先级的线程中放置较少的线程(通过过度使用线程工厂)。有关示例,请参阅https://github.com/tgkprog/ddt/tree/master/DdtUtils/src/main/java/org/s2n/ddt/util/threads
用法:
//setup
PoolOptions options = new PoolOptions();
options.setCoreThreads(2);
options.setMaxThreads(33);
DdtPools.initPool("poolA", options);
Do1 p = null;
// Offer a job:
job = new YourJob();
DdtPools.offer("poolA", job);
也不要使用缓存池,因为它可以根据需要增长,而不是TCP可以无限制地阻止。您想使用受控池。如果需要,可以重新初始化上述库(增加线程数,同时允许当前作业在旧池被丢弃到GC之前进行处理)。
可以为https://github.com/tgkprog/ddt/blob/master/Core/src/main/web/common/poolEnd.jsp和https://github.com/tgkprog/ddt/blob/master/Core/src/main/web/common/threads.jsp
等操作生成实用程序jsp / servlet答案 2 :(得分:0)
如果您的应用程序只有ExecutorServivce,则可以继续使用静态全局。
newCachedThreadPool()
和newFixedThreadPool()
都无法控制Callable/Runnable
任务的队列。 他们使用无界队列,这可能导致系统性能下降。
我更喜欢使用ThreadPoolExecutor,它可以更好地控制各种参数,例如队列大小,拒绝处理程序,线程工厂等。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
或
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
有关详细信息,请参阅以下帖子:
FixedThreadPool vs CachedThreadPool: the lesser of two evils