线程池
核心参数
// 默认拒绝策略为 AbortPolicy
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}
corePoolSize
线程池核心线程数,最小线程数; 核心常驻线程池。如果等于0,任务执行完,没有任何请求进入则销毁线程; 如果大于0,即使本地任务执行完毕,核心线程池也不会被销毁。这个参数设置非常关键设置过大浪费资源,设置过小导致线程频繁创建或销毁。
maximumPoolSize
线程池同时执行的最大现场等是maximumPoolSize表示线程池能够容纳同时执行的最大线程数。
keepAlive
表示线程池中的线程空闲时间,当空闲时间达到keepAliveTime
值时,线程会被销毁,直到只剩下corePoolSize个线程为止,避免浪费内存和句柄资源。 线程空闲后存活时间, 0代表永远不会消失
timeUnit
时间单位通常是TimeUnit.SECONDS。
workQueue 任务容器
当请求的线程数大于corePoolSize时,线程进入BlockingQueue阻塞队列。后续示例代码中使用的LinkedBlockingQueue
是单向链表,使用锁来控制入队和出队的原子性
,两个锁分别控制元素的添加和获取,是一个生产消费模型队列
。
- ArrayBlockintQueue(有界队列):基于数组的有限阻塞队列,先进先出(FIFO),插入数据和取出数据公用一个锁对象;
- LinkedBlockingQueue(无界队列):基于链表的无限阻塞队列,先进先出(FIFO),当请求越来越多时(任务处理速度跟不上任务提交速度造成请求堆积)可能导致内存占用过多或OOM,newFixedThreadPool 和 newSingleThreadExecutor 使用这个队列;
- SynchronousQueue(同步移交队列):不存储元素的阻塞队列,插入操作必须等待一个线程调用移除操作,否则一直会阻塞。newCachedTHreadPool 使用这个队列
ThreadFactory
创建线程的工厂类,默认使用Executors.defaultThreadFactory(),也可以使用guava库的ThreadFactoryBuilder来创建
它用来生产一组相同任务的线程。线程池的命名是通过给这个factory增加组名前缀来实现的。在虚拟机栈分析时,就可以知道线程任务是由哪个线程工厂产生的。
handler
表示执行拒绝策略的对象
• AbortionPolicy (默认):中断直接抛异常
• DiscardPolicy:默默丢弃任务,不进行任何通知
• DiscardOldestPolicy:丢弃打错字了队列中存在时间最久的任务
• CallerRunsPolicy:让提交任务的线程去执行任务
当超过第5个参数workQueue的任务缓存区上限的时候,就可以通过该策略处理请求,这是一种简单的限流保护。
友好的拒绝策略可以是如下三种:
- 保存到数据库或者MQ进行削峰填谷,在空闲时取出来执行。
- 转向友好的提示页面
- 打印日志
直接丢弃任务,将队列头节点元素中的任务丢弃;
构造 ThreadPoolExecutor:
具体查看每个线程池
阻塞队列
new ArrayBlockingQueue();
new LinkedBlockingQueue();
new DelayQueue();
new TransferQueue();
new SynchrousQueue();
非阻塞队列
concurrentlistqueue
低效率并发容器
new Vector();
new Copyonwritelist();
new Hashtable();
synchronized 修饰后的容器
concurrenthashmap
concurrentskiplisthashmap
Executor
用于执行某个任务
ExecutorService
一个服务,在后台一直运行,等待任务抛入(submit),并执行,抛入的任务又分为两个类型:
`Callable` 有返回值
`Runnable` 没有返回值
Executors
是一个用于操作上面对象的工具类和工厂类
ThreadPool
线程池
Future
未来的结果