关于 ExecutorService 的说明
Clarification on ExecutorService
我最近阅读了有关将任务提交到 ExecutorService
的内容,其中任务实现了 Runnable
接口。如果我错了请纠正我但是:
- 据我了解,您可以创建一个
ThreadPool
并具体定义此池可以包含多少个线程。这样做的原因是不是创建一个缓存线程池,如果你给它提供太多任务,后者可能会崩溃?另外,我想知道,对于您希望线程池包含的线程数,您可以传入的最大值是多少?是什么阻止我传递一个毫无意义的任意大整数,比如 100000?
- 即使使用
ExecutorService
到底有什么好处?我知道它为你抽象了一些 instantiation/handling 你的任务,但我想除此之外我对更深层次的了解不多
这是真的吗?
- 有固定线程池的原因是您可能需要限制应用程序创建的线程数(并控制资源使用)。每个进程的线程数没有明确的限制,它取决于OS和主机(通常是内存)。
- 使用执行器服务的好处是您可以通过将一种实现替换为另一种实现来改变您的多线程行为。比如说,您只需在
Executors
上调用不同的方法,就可以从有限数量的线程切换到缓存线程池,而您的代码不需要更改。
启动线程代价高昂,应尽可能避免。线程池缓存线程以减少执行此操作的频率。
线程是一种您可以运行使用的有限资源,因此最好限制启动的最大数量。如果队列中的项目没有得到足够快的处理,您可以增加数量,但您可以以受控的方式进行,这样您就不会因为达到最大值而使 JVM 崩溃。支持的最大值取决于 OS 配置和您使用的硬件。
我喜欢为整个应用程序创建一个线程池,然后将其用于所有类型的后台工作。在 Web 应用程序中,您必须确保在应用程序停止时您的线程也已结束。拥有一个线程池使这很容易。否则你会经常 运行 进入线程泄漏,因为你忘记停止线程。
是的,我知道不建议在 Web 应用程序中启动线程。只要你结束它们,它对我来说就很好。
回答你的第一点:
It is my understanding that you can create a ThreadPool and
specifically define how many threads this pool can contain. Is the
reason for doing this over creating a cached thread pool that the
latter can crash if you feed it too many tasks?
有许多 ExecutorService 的实现,如 newCachedThreadPool()
、newCachedThreadPool(ThreadFactory threadFactory)
、newFixedThreadPool(int nThreads)
,其中许多创建缓存线程池,而许多则不创建,如固定线程池。 固定线程池不是缓存线程池的替代品,但它们都是选项。
因此,开发人员应根据需求进行选择。如果你想完全控制线程池然后有一个固定大小的线程池,并且可以保证无论有多少任务,池中只有那么多线程,这意味着在你的应用程序中有将只是那些额外的线程。
Also, I am wondering, what is the maximum value you can pass in for
the number of threads you want your thread pool to contain? What's to
stop me from passing an arbitrarily large integer that makes no sense,
say 100000?
据我所知,对于可以在线程池中放置多少个线程,没有硬性规定。这实际上取决于您的 JVM 可以处理多少线程。例如,32 位 JVM 可以处理的线程数少于 64 位 JVM。所以,如果你在 64 位 JVM 上,那么你可以更奢侈。
没有什么可以阻止开发人员输入一些无意义的数字,但是 这会导致占用线程、性能下降、内存不足甚至 JVM 崩溃。
回答你的第二点:
What exactly is the benefit of even using an ExecutorService? I
understand that it abstracts some of the instantiation/handling of
your task for you, but I guess other than that I don't understand much
more on a deeper level
真正的优势在于您正在编程接口。因此,您可以选择几个 ExecutorService
实现,例如 ScheduledThreadPoolExecutor
、ThreadPoolExecutor
等。此外,如果您使用 ExecutorService
,例如
,还有许多其他选项可供选择]
- 在固定间隔后启动一个线程
- 一次调用任何任务并让您的线程池执行它们
阅读 ScheduledThreadPoolExecutor
和 ThreadPoolExecutor
中可用的方法,您将了解它们提供的方法的强大功能。
希望这对您有所帮助!
编辑:基于@pens-fan-69 的输入
阅读 this article JVM 可以支持多少线程。
堆栈大小
整个 JVM 进程由 Java 个线程组成,有些是 JVM 内部线程,如主线程、GC 线程、终结器线程等。而有些是用户定义的线程。
无论是内部线程还是用户定义线程, 每个线程都会分配一部分堆栈来放置运行时信息。 JVM 参数 -Xss 定义堆栈大小。例如,如果堆栈大小 (-Xss) 是 64KB,那么这意味着 JVM 中的每个线程将有 64KB 来存储运行时信息。
如果堆栈大小不足,则抛出堆栈溢出异常。
因此,JVM 中可以存在的最大线程数将取决于堆栈大小。 堆栈大小越大,线程数越少,反之亦然。
默认堆栈大小将因 OS 而异。下图:
我最近阅读了有关将任务提交到 ExecutorService
的内容,其中任务实现了 Runnable
接口。如果我错了请纠正我但是:
- 据我了解,您可以创建一个
ThreadPool
并具体定义此池可以包含多少个线程。这样做的原因是不是创建一个缓存线程池,如果你给它提供太多任务,后者可能会崩溃?另外,我想知道,对于您希望线程池包含的线程数,您可以传入的最大值是多少?是什么阻止我传递一个毫无意义的任意大整数,比如 100000? - 即使使用
ExecutorService
到底有什么好处?我知道它为你抽象了一些 instantiation/handling 你的任务,但我想除此之外我对更深层次的了解不多
这是真的吗?
- 有固定线程池的原因是您可能需要限制应用程序创建的线程数(并控制资源使用)。每个进程的线程数没有明确的限制,它取决于OS和主机(通常是内存)。
- 使用执行器服务的好处是您可以通过将一种实现替换为另一种实现来改变您的多线程行为。比如说,您只需在
Executors
上调用不同的方法,就可以从有限数量的线程切换到缓存线程池,而您的代码不需要更改。
启动线程代价高昂,应尽可能避免。线程池缓存线程以减少执行此操作的频率。
线程是一种您可以运行使用的有限资源,因此最好限制启动的最大数量。如果队列中的项目没有得到足够快的处理,您可以增加数量,但您可以以受控的方式进行,这样您就不会因为达到最大值而使 JVM 崩溃。支持的最大值取决于 OS 配置和您使用的硬件。
我喜欢为整个应用程序创建一个线程池,然后将其用于所有类型的后台工作。在 Web 应用程序中,您必须确保在应用程序停止时您的线程也已结束。拥有一个线程池使这很容易。否则你会经常 运行 进入线程泄漏,因为你忘记停止线程。
是的,我知道不建议在 Web 应用程序中启动线程。只要你结束它们,它对我来说就很好。
回答你的第一点:
It is my understanding that you can create a ThreadPool and specifically define how many threads this pool can contain. Is the reason for doing this over creating a cached thread pool that the latter can crash if you feed it too many tasks?
有许多 ExecutorService 的实现,如 newCachedThreadPool()
、newCachedThreadPool(ThreadFactory threadFactory)
、newFixedThreadPool(int nThreads)
,其中许多创建缓存线程池,而许多则不创建,如固定线程池。 固定线程池不是缓存线程池的替代品,但它们都是选项。
因此,开发人员应根据需求进行选择。如果你想完全控制线程池然后有一个固定大小的线程池,并且可以保证无论有多少任务,池中只有那么多线程,这意味着在你的应用程序中有将只是那些额外的线程。
Also, I am wondering, what is the maximum value you can pass in for the number of threads you want your thread pool to contain? What's to stop me from passing an arbitrarily large integer that makes no sense, say 100000?
据我所知,对于可以在线程池中放置多少个线程,没有硬性规定。这实际上取决于您的 JVM 可以处理多少线程。例如,32 位 JVM 可以处理的线程数少于 64 位 JVM。所以,如果你在 64 位 JVM 上,那么你可以更奢侈。
没有什么可以阻止开发人员输入一些无意义的数字,但是 这会导致占用线程、性能下降、内存不足甚至 JVM 崩溃。
回答你的第二点:
What exactly is the benefit of even using an ExecutorService? I understand that it abstracts some of the instantiation/handling of your task for you, but I guess other than that I don't understand much more on a deeper level
真正的优势在于您正在编程接口。因此,您可以选择几个 ExecutorService
实现,例如 ScheduledThreadPoolExecutor
、ThreadPoolExecutor
等。此外,如果您使用 ExecutorService
,例如
- 在固定间隔后启动一个线程
- 一次调用任何任务并让您的线程池执行它们
阅读 ScheduledThreadPoolExecutor
和 ThreadPoolExecutor
中可用的方法,您将了解它们提供的方法的强大功能。
希望这对您有所帮助!
编辑:基于@pens-fan-69 的输入
阅读 this article JVM 可以支持多少线程。
堆栈大小
整个 JVM 进程由 Java 个线程组成,有些是 JVM 内部线程,如主线程、GC 线程、终结器线程等。而有些是用户定义的线程。无论是内部线程还是用户定义线程, 每个线程都会分配一部分堆栈来放置运行时信息。 JVM 参数 -Xss 定义堆栈大小。例如,如果堆栈大小 (-Xss) 是 64KB,那么这意味着 JVM 中的每个线程将有 64KB 来存储运行时信息。
如果堆栈大小不足,则抛出堆栈溢出异常。
因此,JVM 中可以存在的最大线程数将取决于堆栈大小。 堆栈大小越大,线程数越少,反之亦然。
默认堆栈大小将因 OS 而异。下图: