重点内容 线程池的使⽤ 创建线程池 提交任务 关闭线程池 线程池的原理 合理配置线程池 线程池的监控
corePoolSize:线程池的基本大小。 提前调用prestartAllCoreThreads(),会把所有的基本线程启动 。 workQueue: ⽤于保存等待执⾏的任务的阻塞队列。 ArrayBlockingQueue 基于数组实现的(先进先出)。 LinkedBlockingQueue 吞吐量要高于ArrayBlockingQueue。 SynchronousQueue 吞吐量要高于LinkedBlockingQueue 不存储元素的阻塞队列,得等一个线程做移除操作才能继续进行,要不会一直阻塞。 PriorityBlockingQueue 具有优先级的无限阻塞队列。 maximumPoolSize: 线程池允许创建的最⼤线程数。 threadFactory: ⽤于设置创建线程的工厂可以使用谷歌的开源方法。 handler: 饱和策略,阻塞队列和我们的线程的创建数都满了的时候就会饱和选择一个策略对新提交的策略进行处理。 AbortPolicy 直接抛出异常。 CallerRunsPolicy 只用调用者所在的线程来处理任务。 DiscardOldestPolicy 丢弃队列里最近的一个任务。 DiscardPolicy 直接丢弃。 ⾃定义 自己定义一个处理方式。 keepAliveTime:线程池的⼯作线程空闲后,保持存活的时间。 unit:线程活动保持时间的单位。
execute:⽤于提交不需要返回值的任务 submit:⽤于提交需要返回值的任务 shutdown:终止的时候会抛出异常 shutdownNow:中止的时候不会抛出异常
线程池测试代码

首先会判断corePoolSize核心线程池是否已经满了,没满就直接创建线程执行任务,满了再去判断队列是否满了,队列没有满的话在把任务放在队列里面,队列如果满的话,会将当前的线程数量跟maximumPoolSize进行对比如果没满的话就创建线程执行任务,maximumPoolSize也满了话就按照策略(handler)处理无法执行的任务。注意线程池只要创建线程就会获取全局锁。
线程会根据worker去线程池里面拿任务
线程池execute的源码
线程池addWorker的源码
线程池runWorker的源码
任务的性质 CPU密集型 : N cpu + 1 配置尽可能小的线程,线程数要少一点,减少cpu频繁的上下文切换,提高cpu的利用率 IO 密集型 :2 * N cpu 需要配置尽可能多的线程,这样才能保证cpu能被充分的利用 混合型 :拆分成CPU密集型和IO密集型 N = Runtime.getRuntime().availableProcessors() 任务的优先级 :PriorityBlockingQueue 任务的执⾏时间 不同规模的线程池 PriorityBlockingQueue 让执行时间比较短的线程先执行 任务的依赖性 增加线程数量 使⽤有界队列保证系统的稳定性
taskCount 任务的数量 completedTaskCount 运行的过程中完成的任务数量 largestPoolSize 曾经创建过的最大的线程数量 getPoolSize 线程数量 getActiveCount 获取活动的线程数 扩展线程池:beforeExecute、afterExecute 在线程执行前,执行后做点什么