核心线程数:
1.corePoolSize:线程池长期维持的线程数量,即使这些线程处于空闲状态,也不会被销毁,(除非设置了allowCoreThreadTimeOut).
2.maximumPolloSize(最大线程数):
线程池允许创建最大的线程数,当核心线程和队列都满时,会创建非核心线程,知道达到这个数量。
3.keepAliveTime&unit(空闲线程存活时间):非核心线程空闲超过这个时间,就会被销毁,核心线程默认不会被销毁,除非设置了(allowCoreThreadTimeOut(true))
4.workQueue(阻塞队列):
用于存储待执行的任务,当核心都繁忙的时候,任务会被放在队列里面等待。
5.threadFactory(线程工厂):用于创建线程,可自定义线程名称,优先级,是否为守护线程等等。
6.handler(拒绝策略):
当线程数达到最大,队列也满时,新提交的任务会触发拒绝策略。
线程池的执行顺序:
正确的顺序是:核心---队列---非核心---拒绝策略。
具体流程:
1.先去核心是否满,未满直接创建核心线程执行任务。
2.如果核心线程已满,任务会被放入队列等待。
3.如果队列满了,会创建非核心线程池。
4.如果线程已经达到最大,队列也满了,就会触发拒绝策略。
首先:队列是缓冲任务的,能避免不必要的线程的创建,只有队列满了,才说明任务量确实超过了核心线程的处理能力,这时候在创建非核心线程来分担压力。
任务太多了如何优雅的降级:
1.明确告诉:异常,调用方可以捕获异常进行重试和补偿。
2.提交任务的线程,自己执行该任务,比如线程提交的任务就有线程执行,这会减缓任务提交的速度,起到“削峰”的作用。
3.默默丢弃任务:不抛异常,不做任何处理,适用:“可以丢的场景”,比如日志收集。
4.丢弃队列中最老的任务:然后将新任务加入队列,适用于:新任务比旧任务更重要的场景。
动态调整线程:
如果线上运行一段时间,发现线程池参数不合理(比如核心数太小,队列容量太小),不需要重启应用,就可以动态调整,可以根据监控数据自动调优。
当然具体的参数的设置,可以通过压测来进行验证,大家可以通过jemeter来讲进行压测试试。