关于Executor服务的java澄清
我最近读到了关于将任务提交到ExecutorService
的文章,其中的任务实现了Runnable
接口。如果我错了,请纠正我的错误,但是:
- 我的理解是,您可以创建一个
ThreadPool
,并具体定义这个池可以包含多少线程。这样做的原因是因为创建了一个缓存线程池,如果您向它提供太多任务,后者可能会崩溃吗?另外,我想知道,对于希望线程池包含的线程数,您可以传递的最大值是多少?什么能阻止我传递一个毫无意义的任意大整数,比如100000李> - 甚至使用
ExecutorService
的好处到底是什么?我知道它为您抽象了一些任务的实例化/处理,但我想除此之外,我对更深层次的理解不多
这是真的吗
# 1 楼答案
启动线程很昂贵,应该尽可能避免。线程池缓存线程,这样就不那么频繁了
线程是一个有限的资源,您可以用尽,所以最好限制启动的最大数量。如果队列中的项目处理速度不够快,可以增加数量,但可以以可控的方式进行,这样就不会因为达到最大值而导致JVM崩溃。支持的最大值将由您使用的操作系统配置和硬件决定
我喜欢为整个应用程序创建一个单线程池,然后将其用于所有类型的后台工作。在web应用程序中,必须确保应用程序停止时线程结束。拥有一个单线程池使这变得容易。否则,由于忘记停止线程,您将经常遇到线程泄漏
是的,我知道不建议在web应用程序中启动线程。只要你结束他们,对我来说没问题
# 2 楼答案
Executors
上调用不同的方法,就可以从有限数量的线程切换到缓存的线程池,并且不需要更改代码李># 3 楼答案
回答你的第一点:
ExecutorService有许多实现,比如
newCachedThreadPool()
、newCachedThreadPool(ThreadFactory threadFactory)
、newFixedThreadPool(int nThreads)
,其中许多创建了缓存线程池,而许多没有,比如固定线程池固定线程池不是缓存线程池的替代品,但它们都是可选的因此,开发人员应该根据需求进行选择。如果你想完全控制线程池,那么就有一个固定大小的线程池,并且可以保证无论有多少任务,池中都只有那么多线程,这意味着在你的应用程序中只有那么多额外的线程
据我所知,对于你可以在线程池中放入多少线程,没有硬性规定。这实际上取决于JVM可以处理多少线程。例如,32位JVM可以处理的线程数少于64位JVM。因此,如果您使用的是64位JVM,那么您可以享受更多的奢侈
没有什么能阻止开发人员输入一些无意义的数字,但这样做的后果是占用线程、性能下降、内存不足,甚至JVM崩溃
回答你的第二点:
真正的优势来自这样一个事实,即您正在对接口进行编程。因此,您可以选择几个
ExecutorService
实现,比如ScheduledThreadPoolExecutor
、ThreadPoolExecutor
等等。此外,如果您使用ExecutorService
等,您还可以选择许多其他选项阅读
ScheduledThreadPoolExecutor
和ThreadPoolExecutor
中提供的方法,你会意识到它们提供的方法的威力希望这有帮助!
编辑:基于@pens-fan-69的输入 阅读this article了解JVM可以支持多少线程
堆栈大小
整个JVM进程由Java线程组成,有些是内部JVM线程,如主线程、GC线程、终结器线程等,而有些是用户定义的线程无论它是内部线程还是用户定义的线程,每个线程都将有一部分堆栈分配给它以放置运行时信息JVM参数-Xss定义堆栈大小。例如,如果堆栈大小(-Xss)为64KB,则意味着JVM中的每个线程将有64KB来存储运行时信息。
如果堆栈大小不足,则会引发堆栈溢出异常
因此,JVM中可以存在的最大线程数将取决于堆栈大小堆栈大小越大,线程数越少,反之亦然
默认堆栈大小因操作系统而异。下图: