java多线程(并发)夯实之路-线程池深入浅出

线程池

Thread Pool:线程池,存放可以重复使用的线程(消费者)

Blocking Queue:阻塞队列,存放等待执行的任务(生产者)

java多线程(并发)夯实之路-线程池深入浅出_第1张图片

poll方法(有时限地获取任务)相对take注意防止线程 一直等待

take死等&poll超时

阻塞获取和阻塞添加失败时会进入对应的条件变量等待,阻塞获取和阻塞添加操作成功后唤醒对方

java多线程(并发)夯实之路-线程池深入浅出_第2张图片

java多线程(并发)夯实之路-线程池深入浅出_第3张图片

线程池实现部分:

java多线程(并发)夯实之路-线程池深入浅出_第4张图片

线程池execute方法:当任务没有超过核心线程数量,直接交给worker对象执行,当任务超过核心线程数量,进入任务队列缓存

线程池worker中run方法:当task不为空,执行任务,task执行完毕,接着从任务队列中获取任务并

执行

任务队列已满,添加任务时的操作可以由调用者自己选择

死等:await等待影响性能

带超时等待:offer方法

让调用者放弃任务执行

让调用者抛出异常

让调用者自己执行任务

java多线程(并发)夯实之路-线程池深入浅出_第5张图片

ThreadPoolExecutor

ThreadPoolExecutor使用int的高三位来表示线程池状态,低29位表示线程数量

java多线程(并发)夯实之路-线程池深入浅出_第6张图片

把线程池状态和线程数量的信息存储在一个原子变量ctl中,进行cas原子操作就只需要一次

java多线程(并发)夯实之路-线程池深入浅出_第7张图片

java多线程(并发)夯实之路-线程池深入浅出_第8张图片

最大线程数:核心线程数与救急线程数之和

任务需要执行时才去创建线程,核心线程不会被销毁

阻塞队列放不下的任务由救急线程执行,救急线程也不够使用,才会执行拒绝策略

生存时间:救急线程没有任务需要执行后等待的时间,时间结束后销毁

选择有界队列才有救急线程

线程数达到maximumPoolSize仍有新任务才会执行拒绝策略

java多线程(并发)夯实之路-线程池深入浅出_第9张图片

newFixedThreadPool:固定大小线程池(没有救急线程,无超时时间),阻塞队列时无界的,可以放任意数量的任务

使用场景:任务量已知,相对耗时的任务

java多线程(并发)夯实之路-线程池深入浅出_第10张图片

newCachedThreadPool:带缓存线程池,线程都是救急线程(60s后可以回收),并且可以无限创建

队列采用synchronousQueue,特点:没有容量,任务只能被线程完成,不能添加进任务队列

java多线程(并发)夯实之路-线程池深入浅出_第11张图片

线程池特点:线程数随任务量不断增加,没有上限,任务执行完空闲1分钟后释放线程使用场景:任务数量多,执行快

newSingleThreadExecutor:单线程线程池,线程数固定为1,多的任务放入无界队列排队,线程不会释放

使用场景:任务排队执行

区别:任务执行失败会新建一个线程,保证池正常运行;线程个数始终位1,不能修改(只对外暴露ExecutorService接口不能调用ThreadPoolExecutor中特有的方法,而不是暴露ThreadPoolExecutor对象可以强转后调用setCorePoolSize等方法进行修改)

java多线程(并发)夯实之路-线程池深入浅出_第12张图片

提交任务的方法

java多线程(并发)夯实之路-线程池深入浅出_第13张图片

java多线程(并发)夯实之路-线程池深入浅出_第14张图片

java多线程(并发)夯实之路-线程池深入浅出_第15张图片

java多线程(并发)夯实之路-线程池深入浅出_第16张图片

停止线程池
void shutdown:状态变为SHUTDOWN,不会接收新任务,但已提交的任务会执行完,不会阻塞调用线程的执行。打断空闲线程。
List shutdownNew:状态变为STOP,会将队列中任务返回,用interrupt的方式打断正在执行的任务。打断所有线程。

java多线程(并发)夯实之路-线程池深入浅出_第17张图片

java多线程(并发)夯实之路-线程池深入浅出_第18张图片

其它方法:

awaitTermination:超时时间结束或任务运行完,调用该方法的线程才继续往下运行

java多线程(并发)夯实之路-线程池深入浅出_第19张图片

你可能感兴趣的:(java,开发语言)