为什么需要线程池?
因为频繁的创建和销毁线程需要大量时间和资源。为了防止资源不足,应该尽可能减少线程的创建和销毁,使用已经存在的线程。
线程池是线程的容器,其内部有多个线程,可以重复使用,这样就可以避免反复创建销毁线程消耗过多资源
数据库连接池跟线程池是一样的道理。
数据库的连接和断开都是耗时耗资源的操作,应该减少连接断开次数,尽可能使用已经有的连接。
数据库连接池就是预先创建一组连接,用的时候取,用完就放回。减少连接断开的次数,提高利用率。
java里面线程池的顶级接口时Excutor,但是真正的线程池接口时ExcutorService,默认的实现类是ThreadPoolExcutor。Excutors是线程池创建工厂类(生产线程池的工厂) 也是调用的ThreadPoolExcutor
Excutors提供的四种线程池
1.newCachedThreadPool 最大线程数可无限扩大的线程池,容易积压大量任务造成OOM
2.newSingleThreadPool核心线程数为1最大线程数为1 但是等待队列2的31次-1容易积压大量请求OOM
3.newFixedThreadPool线程数固定但是阻塞队列最大为2的31次-1
4.newScheduledThreadPool 最大线程数无限,容易积压大量任务OOM
不建议使用Excutors提供的四种线程池,需要自己创建线程池,创建之前就必须了解线程池的参数
1.corePoolSize 核心线程数
2.maxmumPoolSize 最大线程数
3.keepAliveTime 线程最长闲置时间
4.unit 线程最长闲置时间的单位
5.workQueue 阻塞队列的大小
6.ThreadFactory 线程制造工厂
7.rejectedExcutionHandler 拒绝策略
线程池工作流程
4种拒绝策略
1.abortPolicy 直接抛出异常
2.callRunnersPolicy 将任务返回给调用者
3.discardOldestPolicy把等待队列中等待最久的任务抛弃,加入新的任务并提交
4.discardPolicy 什么都不做不抛出异常不做任何处理,如果允许任务丢失这是最好的策略
线程池的关闭:
shutDown 不会立刻停止,不接受新的任务把所有任务做完再停止
shuDownNow 立刻停止线程池 并试图打断当前运行的任务,返回未执行的任务。