1.线程池是什么
线程池做的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过最大数量的线程排队等待,等其他线程执行完成,再从队列中取出任务来执行。
2.线程池的优点
1.降低支援消耗,使用线程池可以减少创建和销毁线程的消耗。
2.提高效率,任务可以不需要的等到线程创建完就能立即执行
3.提高线程的可管理性,线程是稀缺资源,如果无限制的创建,会降低系统的稳定性,使用线程可以进行统一的分配
3.创建线程池的三个方法和七个参数
Java提供的三种线程池实现
1.Executors.newFixedThreadPool(int):执行长期的任务,性能好很多创建一个定长线程池,可以控制线程最大并发量,超出的线程会在队列中等待
2.Executors.newSignleThradExecutor():一个任务一个任务执行的场景创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照顺序执行
3.Executors.newCachedThreadPool():执行很多短期异步的小程序,创建一个可缓存线程池,如果线程长度成功处理需要,可灵活回收空闲线程,若无回收,则新建线程
创建线程池需要的七个参数
1.corePoolSize:线程池中的常驻核心线程数,处理任务的线程
2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1
3.keepAliveTime:多余的空闲线程的存活时间,当前线程数量超过corePoolSize时,当空闲时间达到 keepAliveTime值时
4.unit:keepAliveTime的单位
5.workQueue:任务队列,被提交但未被执行的任务
6.threadFactory:表示生成的线程池中工作线程工厂,用于创建线程一般用于默认的即可
7.handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数 (maximumPoolSize)会开启策略模式
4.线程池的实现原理
1.在创建了线程池后,等待提交过的任务请求
2.当调用execute()方法添加一个请求任务时,线程池会做下判断
3.如果正在运行的线程小于corePoolSize,那么马上创建线程运行这个任务
4.如果正在运行的线程数量大于或等于corePoolSize,那么将任务存放到workQueue任务队列
5.如果这时队列满了且正在运行的线程数量还小于线程池能够容纳同时执行的最大线程数maximumPoolSize,那么还是要创建非核
6.如果队列满了且正在运行的线程数量大于或等于能够容纳同时执行的最大线程数maximumPoolSize,那么线程会启动饱和和拒绝策略来执行
7.当一个线程完成任务时,它会从队列中取下一个任务来执行
8.当一个线程无事可做超过一定的时间(keepAliveTime)时,线程会判断,如果当前线程运行的线程 数量大于corePoolSize,那么这个线程就会被停止
线程池handler的四种拒绝策略
1.AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行
2.CallerRunsPolicy:调用者运行一种调节机制,该策略既不会抛出任务,也不会抛出异常,而是将某 一个回退到调用者
3.DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列尝试再次提交当前 任务
4.DiscardPolicy:直接抛弃,不做任何处理也不会抛出异常。
总结:处理线程判断的优先级为 核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler拒绝策略处理被拒绝的任务
5.配置线程池大小配置
一般是根据类型配置计算的线程池大小
如果是CPU型,CPU型指的是计算类型:CPU核数+1线程
如果是IO型,读写类型:CPU核数 / 1-0.9
当然,这只是推荐的算法,具体的设置还需要根据实际情况进行调整