陷阱 - 太多线程使应用程序变慢
许多不熟悉多线程的人认为使用线程会自动使应用程序更快。事实上,它要复杂得多。但有一点我们可以肯定地说,对于任何计算机,可以同时运行的线程数量有限制:
- 计算机具有固定数量的核心 (或超线程 )。
- 必须将 Java 线程调度到核心或超线程才能运行。
- 如果有比可用的核心/超线程更多的可运行 Java 线程,则其中一些必须等待。
这告诉我们,简单地创建越来越多的 Java 线程无法使应用程序变得越来越快。但是还有其他一些考虑因素:
-
每个线程都需要一个用于其线程堆栈的堆外内存区域。典型(默认)线程堆栈大小为 512K 字节或 1M 字节。如果你有大量线程,则内存使用量可能很大。
-
每个活动线程将引用堆中的许多对象。这增加了可到达对象的工作集,这会影响垃圾收集和物理内存使用。
-
线程之间切换的开销非常重要。它通常需要切换到 OS 内核空间以进行线程调度决策。
-
线程同步和线程间信令(例如
wait()
,notify()/ notifyAll)的开销可能很大。
根据应用程序的详细信息,这些因素通常意味着线程数量存在最佳位置。除此之外,添加更多线程可以最大限度地提高性能,并且可以使性能变差。
如果你的应用程序为每个新任务创建,那么工作负载的意外增加(例如,高请求率)可能导致灾难性行为。
处理此问题的更好方法是使用有界线程池,其大小可以控制(静态或动态)。当有太多工作要做时,应用程序需要对请求进行排队。如果使用 ExecutorService
,它将负责线程池管理和任务排队。