学习线程池首先要知道什么是线程池,为什么要使用线程池,再去了解他的工作流程以及参数配置。
什么是线程池?
顾名思义,线程池就是管理一系列线程的资源池。当有任务要处理时,直接从线程池中获取线程来处理,处理完之后线程并不会立即被销毁,而是等待下一个任务。
为什么要使用线程池?
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
线程池工作流程
当任务通过executor提交给线程池的时候,我们需要知道下面几个点:
-
当池中工作线程数小于corePoolSize(核心线程数) 的时候,每次来任务的时候都会创建一个新的工作线程。
-
当池中工作线程数大于等于corePoolSize 的时候,每次任务来的时候都会首先尝试将线程放入队列(如果阻塞队列未满的话),而不是直接去创建线程。
-
如果放入队列失败,且当先池中线程数小于maximumPoolSize的时候,则会创建一个工作线程。如果池中线程数大于maximumPoolSize,就会用拒绝策略。
线程池各参数
-
corePoolSize
(核心线程数): 任务队列未达到队列容量时,最大可以同时运行的线程数量。 -
maximumPoolSize
(最大线程数): 任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。 -
keepAliveTime
(存活时间):线程池中的线程数量大于corePoolSize
的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime
才会被回收销毁。. -
unit
(时间单位):keepAliveTime
参数的时间单位。 -
workQueue
(任务队列): 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。几种常见的工作队列可以去了解一下。 -
threadFactory
(线程工厂):executor 创建新线程的时候会用到,用来创建线程。 -
handler
:拒绝策略。下面是线程池的4中拒绝策略。-
ThreadPoolExecutor.AbortPolicy
:抛出RejectedExecutionException
来拒绝新任务的处理。 -
ThreadPoolExecutor.CallerRunsPolicy
:如果线程池无法接受新任务,则由主线程(提交任务的线程)自己执行这个任务。这种策略不会抛弃任务,而是直接在主线程中执行。 -
ThreadPoolExecutor.DiscardPolicy
:当线程池无法接受新任务时,不做任何处理,直接丢弃无法执行的任务。 -
ThreadPoolExecutor.DiscardOldestPolicy
:当线程池无法接受新任务时,丢弃最早加入工作队列但尚未被执行的任务,然后尝试将新任务添加到队列中。
-