一、线程池
在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程
(1)线程池的作用
1、降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
2、提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
3、提高线程的可管理性。
(2)常用线程池
ExecutorService 是主要的实现类
1、newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务, 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
适用场景:任务少 ,并且不需要并发执行
2、newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.
适用场景:处理任务速度 > 提交任务速度,耗时少的任务(避免无限新增线程)
3、newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
4、newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行
(3)ThreadPoolExecutor构造方法参数说明
1、corePoolSize
核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。
2、maximumPoolSize
线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。
3、keepAliveTime
非核心线程的闲置超时时间,超过这个时间就会被回收。
4、unit
指定keepAliveTime的单位,如TimeUnit.SECONDS。当将allowCoreThreadTimeOut设置为true时对corePoolSize生效。
5、workQueue
线程池中的任务队列,常用的有三种队列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。
6、threadFactory
线程工厂,提供创建新线程的功能。ThreadFactory是一个接口,只有一个方法
(4)线程池原理
1、当前池大小 poolSize 小于 corePoolSize ,则创建新线程执行任务。
2、当前池大小 poolSize 大于 corePoolSize ,且等待队列未满,则进入等待队列
3、当前池大小 poolSize 大于 corePoolSize 且小于 maximumPoolSize ,且等待队列已满,则创建新线程执行任务。
4、当前池大小 poolSize 大于 corePoolSize 且大于 maximumPoolSize ,且等待队列已满,则调用拒绝策略来处理该任务。
线程池里的每个线程执行完任务后不会立刻退出,而是会去检查下等待队列里是否还有线程任务需要执行,如果在 keepAliveTime 里等不到新的任务了,那么线程就会退出。
(5)Executor拒绝策略
1、AbortPolicy
为java线程池默认的阻塞策略,不执行此任务,而且直接抛出一个运行时异常,切记ThreadPoolExecutor.execute需要try catch,否则程序会直接退出.
2、DiscardPolicy
直接抛弃,任务不执行,空方法
3、DiscardOldestPolicy
从队列里面抛弃head的一个任务,并再次execute 此task。
4、CallerRunsPolicy
在调用execute的线程里面执行此command,会阻塞入
用户自定义拒绝策略:实现RejectedExecutionHandler,并自己定义策略模式