我可以想象一些任务计划花费很长时间,而ScheduledThreadPoolExecutor
会为需要运行的其他任务创建额外的线程,直到达到最大线程数。
但似乎我只能为池指定固定数量的线程,为什么会这样呢?
答案 0 :(得分:11)
作为原因,我也不知道。但我可以想象。
计算机的资源量有限。并非所有资源都可以同时处理。
如果多个进程同时加载文件,它们的加载速度会比顺序加载(至少在硬盘上)。
处理器对同时处理多个线程的支持也很有限。在某些时候,操作系统或JVM将花费更多时间来切换线程,而不是线程执行代码。
这是ScheduledThreadPoolExecutor
按原样设计的一个很好的理由。您可以在队列中放置任意数量的作业,但是从不会同时执行比可以有效运行的更多作业。当然,由你来平衡它。
如果您的任务是IO绑定的,我会将池大小设置得很小,如果它们是CPU绑定的,则会稍大一些(大约32个)。您还可以创建多个ScheduledThreadPoolExecutor
,一个用于IO绑定任务,一个用于CPU绑定任务。
答案 1 :(得分:7)
在进一步深入了解SchecduledThreadPoolExecutor时,我发现了这个link,这个链接解释了SchecduledThreadPoolExecutor解决了Timer类的许多问题。并且引入SchecduledThreadPoolExecutor的原因是替换Timer(由于Timer的各种问题)。 我认为传递给SchecduledThreadPoolExecutor的固定线程数的原因是这个类解决的问题之一。即
Timer类只启动一个 线。虽然效率更高 而不是每个任务创建一个线程,它是 不是最佳解决方案。最优 解决方案可能是使用了多个 一个线程之间的线程为所有 任务和每个任务一个线程。在 效果,最好的解决方案是放置 线程池中的任务。该 池中的线程数应该是多少 施工期间可分配给 允许程序确定 池中的最佳线程数。
所以在我看来,这是SchecduledThreadPoolExecutor的用例来自何处。在您的情况下,您应该能够根据您计划安排的任务以及完成这些任务所需的时间来确定最佳值。如果我有4个长时间运行的任务被安排在同一时间,我宁愿我的池大小大于4,如果有其他任务在同一时间执行。我还希望在不同的执行程序中分离长时间运行的任务,如前面的答案中所示。
希望这会有所帮助:)
答案 2 :(得分:4)
根据Java Concurrency In Practice,无限制线程创建存在以下缺点:
线程生命周期开销
线程创建和拆解不是免费的。线程创建需要时间,并且需要JVM和OS的一些处理活动。
资源消耗
活动线程消耗系统资源,尤其是内存。当可运行线程数多于可用处理器时,线程处于空闲状态。拥有许多空闲线程可能占用大量内存,给垃圾收集器带来压力,并且让许多线程竞争CPU也会带来其他性能成本。如果你有足够的线程来保持所有的CPU忙,那么创建更多的线程将无济于事,甚至可能会受到伤害。
<强>稳定性强>
可以创建多少个线程是有限制的。该限制因平台而异,并受到以下因素的影响:JVM调用参数,Thread构造函数中请求的堆栈大小以及底层操作系统放置的线程限制。当你达到htis limit时,最有可能的结果是OutOfMemoryError。试图从这样的错误中恢复是非常危险的;构建程序以避免达到此限制要容易得多。
在某一点上,更多线程可以提高吞吐量,但是超过这一点,创建更多线程会降低应用程序速度,并且创建一个线程太多会导致整个应用程序崩溃。避免危险的方法是对应用程序创建的线程数量进行限制,并彻底测试应用程序,以确保即使达到此限制,也不会耗尽资源。
无限制的线程创建在原型设计和开发过程中似乎可以正常工作,只有在部署应用程序并且负载很重时才会出现问题。