多线程与高并发编程(七)【线程池一】
- 一、线程池前置
- 二、线程池
- 1. ThreadPoolExecutor
- ① 核心线程数:最开始时存在线程,不会被生存时间限制未活跃时间,可以一直存在(有一个方法可以让核心线程参与,但一般不会指定)。
- ② 最大线程数:核心线程+非核心线程,最大可以扩充到多少。
- ③ 生存时间:多长时间线程(非核心线程)没活干之后,归还空间给OS。
- ④ 生存时间单位:意如其名。
- ⑤ 任务队列:上一篇《多线程与高并发编程(六)【容器】》之中讲的那些队列。
- ⑥ 线程工厂:一个创建线程的工厂,图中用的是默认JDK写好的,也可以自定义,需要实现ThreadFactory接口,里面只有一个newThread()
- ⑦ 拒绝策略:线程池忙而且任务队列等待的满了则进行拒绝策略。JDK默认提供了四种拒绝策略,可以自定义。
- 2. ForkJoinPool 分解 汇总
一、线程池前置
1. Executor接口 executor()
2. ExecutorSevice接口,定义了很多线程池的生命周期的方法
submit() 提交callable接口给线程池运行,异步的,当前线程提交一下就离开了
3. Callable接口(定义了call()),类似runnable,是一个任务,但是相比runnable中的run()多了个返回值。
4. Future接口,承接ExecutorService方法中的返回值,是一个结果
future.get() 阻塞的,等待什么时候future中有返回值运行
5. FutureTak类,既是一个任务(runnable),又是一个结果(更好用的)
自己可以定义任务,也可以承接返回值。
6. CompletableFuture,本身可以承接数据(有兴趣可以研究,内容非常多,是一个比较高层的类)
.supplyAsync(callable) 分一个线程异步的进行操作 ret = 本身
.allOf(CompletableFuture1, CompletableFuture2…) 合并参数里面的多个任务,其中只要有一个任务有返回值,则全部结束
.thenApply(operate) 接着执行
.thenAccept(operate)
二、线程池
线程池JDK一共提供了大体两个:
ThreadPoolExecutor、ForkJoinPool
一个线程池维护两个集合(用的HashSet),一个集合是一个个任务,一个集合是一个个线程。
1. ThreadPoolExecutor
手工定义一个线程池:
上图中线程池的七个参数含义(大厂面试高频背过):
① 核心线程数:最开始时存在线程,不会被生存时间限制未活跃时间,可以一直存在(有一个方法可以让核心线程参与,但一般不会指定)。
② 最大线程数:核心线程+非核心线程,最大可以扩充到多少。
③ 生存时间:多长时间线程(非核心线程)没活干之后,归还空间给OS。
④ 生存时间单位:意如其名。
⑤ 任务队列:上一篇《多线程与高并发编程(六)【容器】》之中讲的那些队列。
⑥ 线程工厂:一个创建线程的工厂,图中用的是默认JDK写好的,也可以自定义,需要实现ThreadFactory接口,里面只有一个newThread()
defaultThreadFactory()源码如下
new Thread() 起一个线程和名字
isDaemon() 是否是守护线程,如果是那就把它变成非守护线程
setPriority() 设置优先级是普通
⑦ 拒绝策略:线程池忙而且任务队列等待的满了则进行拒绝策略。JDK默认提供了四种拒绝策略,可以自定义。
四种拒绝策略:
Abort 抛异常
Discard 扔掉,不抛异常
DiscardOldest 扔掉排队时间最久的
CallerRuns 调用者处理任务(哪个线程提交的这个任务哪个线程去处理它)
2. ForkJoinPool 分解 汇总
北京马士兵教育学习笔记整理