1.为什么使用线程池:
1. 减少线程频繁的创建跟销毁带来的性能消耗
2. 便于管理线程
3. 提高响应速度(不用等待线程创建)
4. 能提供更多的功能
2.线程池的创建方式:
-
通过Executors创建
-
通过ThreadPoolExecutor创建(提倡)
3.线程池的参数说明:
corePoolSize
MaxinumPoolSize
keepAliveTime
TimeUint unit
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler
4.线程池的流程:
-当有任务的时候,如果当前线程数小于核心线程数,那么先创建核心线程数去执行任务。
当线程数已达到核心线程数时,则将任务加入到阻塞队列中去。当阻塞队列满了之后,如果当前线程数大于核心线程数,小于最大线程数时,则创建非核心线程数去执行。如果不满足,则执行拒绝策略
线程池的状态:
Running-ShowDown-ShowDownNow-Stop-Tidying-Terminated
5.线程池的几个重要方法来深入底层原理
-excute(Runnable command)
-addWorker(Runnable fistTask,boolean core)
小结:
–addWorker方法有三种不同的参数调用,在增加任务的过程中,对线程池状态跟线程数进行了多次判断
addWorker(first,true):小于核心线程数,创建核心线程去 执行任务
addWorker(null,false):添加到阻塞队列中去,线程数<最大线程数
addWorker(first,false):阻塞队列已满,创建新的非核心线程去执行任务
-runWorker(Worker w)
-getTask()
-processWorkerExit(Worker w,boolean completedAbruptly)
6.线程池技术亮点:
线程池通过使用CAS跟AutomicInteger来改变线程数量跟线程状态,核心参数用Volatile来修饰,同时使用Condition、ReentrantLock对创建线程的过程,线程池状态的改变,工作任务数量的改变(添加跟删除)等,来通过allowCoreThreadTimeOut || wc > corePoolSize来判断使用poll还是take方法或者任务,Worker同时也继承了AQS(不可重入,线程运行时就不会中断)
7.使用线程池需要注意的点:
1.合理的设置核心线程、最大线程数,充分利用资源,同时也要避免资源的浪费。
2.选择好拒绝策略,注意抛出异常的处理。
3.不合理的设置阻塞队列,选用了LinkedBlockedQueue导致线程池溢出
4.重复创建的线程池,记得showdown
5.根据业务需要,设置allowCoreThreadTimeOut(true),回收被阻塞的核心线程
8. 简单自定义线程池名字:区分不同业务下的线程池
9. 简单自定义拒绝策略