为什么ScheduledThreadPoolExecutor只接受固定数量的线程?

我可以想象一些任务计划需要很长时间,而ScheduledThreadPoolExecutor会为需要运行的其他任务创建其他线程,直到达到最大线程数。

但似乎我只能为池指定固定数量的线程,为什么会这样呢?

作为原因,我也不知道。 但我可以想象。

计算机的资源量有限。 并非所有资源都可以同时处理。

如果多个进程同时加载文件,它们的加载速度将比顺序加载(至少在硬盘上)。

处理器对同时处理多个线程的支持也有限。 在某些时候,操作系统或JVM将花费更多时间来切换线程,而不是线程花费在执行代码上。

这是ScheduledThreadPoolExecutor按原样设计的一个很好的理由。 您可以在队列中放置任意数量的作业,但从不会同时执行比可以有效运行的更多作业。 当然,由你来平衡。

如果你的任务是IO绑定的,我会将池大小设置得很小,如果它们是CPU绑定的,那就更大一点(32左右)。 您还可以创建多个ScheduledThreadPoolExecutor ,一个用于IO绑定任务,另一个用于CPU绑定任务。

在进一步深入了解SchecduledThreadPoolExecutor时,我找到了这个链接 ,这个链接解释了SchecduledThreadPoolExecutor解决了Timer类的许多问题。 并且引入SchecduledThreadPoolExecutor的原因是更换Timer(由于Timer的各种问题)。 我认为传递给SchecduledThreadPoolExecutor的固定线程数的原因是这个类解决的问题之一。 即

Timer类只启动一个线程。 虽然它比为每个任务创建一个线程更有效,但它不是最佳解决方案。 最佳解决方案可以是在一个线程之间为所有任务使用多个线程,在每个任务中使用一个线程。 实际上,最好的解决方案是将任务放在线程池中。 在构造期间,池中的线程数应该是可分配的,以允许程序确定池中的最佳线程数。

所以在我看来,这是SchecduledThreadPoolExecutor的用例来自何处。 在您的情况下,您应该能够根据您计划安排的任务和完成这些任务所需的时间来确定最佳值。 如果我有4个长时间运行的任务被安排在同一时间,我希望我的池大小大于4,如果有其他任务在同一时间执行。 如前面的答案中所示,我还希望在不同的执行程序中分离长时间运行的任务。

希望这可以帮助 :)

根据Java Concurrency In Practice ,无限制线程创建存在以下缺点:

线程生命周期开销

线程创建和拆解不是免费的。 线程创建需要时间,并且需要JVM和OS的一些处理活动。

资源消耗

活动线程消耗系统资源,尤其是内存。 当可运行线程数多于可用处理器时,线程处于空闲状态。 拥有许多空闲线程可能会占用大量内存,给垃圾收集器带来压力,并且让许multithreading竞争CPU也会带来其他性能成本。 如果你有足够的线程来保持所有CPU忙,那么创建更多的线程将无济于事甚至可能会受到伤害。

稳定性

可以创建多少个线程是有限制的。 该限制因平台而异,并受到以下因素的影响:JVM调用参数,Thread构造函数中请求的堆栈大小以及底层操作系统放置的线程限制。 当你达到htis limit时,最可能的结果是OutOfMemoryError。 试图从这样的错误中恢复是非常危险的; 构建程序以避免达到此限制要容易得多。


在某一点上,更多的线程可以提高吞吐量,但是超过这一点,创建更多的线程会降低应用程序的速度,并且创建一个线程太多会导致整个应用程序崩溃。 避免危险的方法是对应用程序创建的线程数量进行限制,并彻底测试应用程序,以确保即使达到此限制,也不会消耗资源。

在原型设计和开发过程中,无限制的线程创建似乎可以正常工作,只有在部署应用程序并且负载很重时才会出现问题。