线程池
线程池就是管理线程的资源池,有任务需要处理时,直接从线程池中取得线程进行处理,处理完成后线程会被放回线程池中,而不是立即销毁。Java 已经提供了线程,为什么还需要使用线程池?
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
如何创建线程池
Java 中创建线程池有两种方法:ThreadPoolExecutor 和 Executor 框架。
- 使用 ThreadPoolExecutor 来创建线程池(推荐)。使用这种方式可以使得程序员更加明确线程池的运行规则,规避资源耗尽的风险。
- 通过 Executor 框架的工具类 Executors 来创建,可以构造多种类型的线程池。这其实就是队 ThreadPoolExecutor 构造函数的封装。
使用 Executors 创建线程池的弊端如下:
FixedThreadPool
和SingleThreadExecutor
:使用的是无界的LinkedBlockingQueue
,任务队列最大长度为Integer.MAX_VALUE
,可能堆积大量的请求,从而导致 OOM。
CachedThreadPool
:使用的是同步队列SynchronousQueue
,允许创建的线程数量为Integer.MAX_VALUE
,如果任务数量过多且执行速度较慢,可能会创建大量的线程,从而导致 OOM。
ScheduledThreadPool
和SingleThreadScheduledExecutor
:使用的无界的延迟阻塞队列DelayedWorkQueue
,任务队列最大长度为Integer.MAX_VALUE
,可能堆积大量的请求,从而导致 OOM。