什么是线程池
线程池,字面意思就是一个创建线程的池子,它的特点就是,在使用线程之前,就一次性把多个线程创建好,放到"池”当中。后面需要执行任务的时候,直接从"线程池"当中通过线程执行。当线程执行完毕之后,也不是直接销毁线程,而是把线程重新放回到"池子“当中,等需要再次执行任务的时候,就再次从池子当中获取线程,执行任务。
如图
线程池常用接口和类
Executor: 线程池顶级接口
ExecutorService:线程池接口,可通过submit(Runnable task)提交任务,用来定义线程池的实现规范的接口(同时继承于Executor接口)
Executors工具类:通过此类可以获得一个线程池,并且里面有配置好的线程池可供选择
通过工具类可以创建四种常用线程池
ExecutorService executorService = Executors.newCachedThreadPool();ExecutorService executorService1 = Executors.newFixedThreadPool(10);ExecutorService executorService2 = Executors.newSingleThreadExecutor();ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
newCachedThreadPool():没有核心线程数,创建一个动态的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
newFixedThreadPool(10):创建固定数目线程的线程池,参数即使核心线程池数也是最大线程池数量
newSingleThreadExecutor():创建一个单线程化的Executor,核心线程数与最大线程数都为1
Executors.newScheduledThreadPool():能够进行任务调度的线程池
线程池的执行流程
首先当线程池空闲时,会进行以下步骤进行操作
- 提交任务:当有人需要执行任务时,通过`execute()`或`submit()`方法提交任务到线程池,线程池会将任务放入任务队列中,等待线程来执行
- 然后选择线程执行任务:线程池会从任务队列中选择一个任务,然后从线程池中选择一个空闲的线程来执行任务。
- 再执行任务:选中线程开始执行任务。线程执行任务期间,会不断从任务队列中获取任务并执行,直到任务队列为空或线程池被关闭
当线程池中不存在空闲线程时
- 如果没有空闲线程,则去判断核心线程池是否已满,如果没有则创建核心线程执行任务
- 否则则去进入工作队列进行等待,如果有线程空闲则立刻分配
- 当工作队列也满时,会去线程池里创建普通线程去执行任务
- 当普通线程池也满时,证明当前线程池已经不能再进行任务的执行了
- 这个时候就会执行拒绝策略