Executor框架、ThreadPoolExecutor、3种常见的线程池
参考:https://blog.csdn.net/javazejian/article/details/50890554
1. Executor框架
为什么需要线程池?
在java中,使用线程来执行异步任务时,线程的创建和销毁需要一定的开销,如果我们为每一个任务创建一个新的线程来执行的话,那么这些线程的创建与销毁将消耗大量的计算资源。
同时为每一个任务创建一个新线程来执行,这样的方式可能会使处于高负荷状态的应用最终崩溃。
所以线程池的出现为解决这个问题带来曙光。
我们将在线程池中创建若干条线程,当有任务需要执行时就从该线程池中获取一条线程来执行任务,如果一时间任务过多,超出线程池的线程数量,那么后面的线程任务就进入一个等待队列进行等待,直到线程池有线程处于空闲时才从等待队列获取要执行的任务进行处理,以此循环.....这样就大大减少了线程创建和销毁的开销,也会缓解我们的应用处于超负荷时的情况。
1.1 Executor框架的两级调度模型
在java线程启动时会创建一个本地操作系统线程,当该java线程终止时,这个操作系统线程也会被回收。
而每一个java线程都会被一对一映射为本地操作系统的线程,操作系统会调度所有的线程并将它们分别给可用的CPU。
而所谓的映射方式是这样实现的:
- 在上层,java多线程程序通过把应用分为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定数量的线程;
- 在底层,操作系统内核将这些线程映射到硬件处理器上。这样种两级调度模型如下图所示:
从图中我们可以看出,应用程序通过Executor框架控制上层的调度,而下层的调度由操作系统内核控制,下层的调度不受应用程序的控制。
1.2 Executor框架的结构
Executor框架的结构主要包括3个部分
- 任务:包括被执行任务需要实现的接口:Runnable接口或Callable接口
- 任务的执行:包括任务执行机制的核心接口Executor,以及继承自Executor的EexcutorService接口。Exrcutor有两个关键类实现了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)
- 异步计算的结果:包括接口Future和实现Future接口的FutureTask类
这些类间的关系的UML图:
- Extecutor是一个接口,它是Executor框架的基础,它将任务的提交与任务的执行分离开来。
- ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务。
- ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。
- ScheduledThreadPoolExecutor比Timer更灵活,功能更强大。
- Future接口和实现Future接口的FutureTask类,代表异步计算的结果。
- Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor或者ScheduledThreadPoolExecutor执行。区别就是Runnable无法返回执行结果,而Callable可以返回执行结果。
- Executor 和 ExectorService 这两个接口的主要区别:
- ExectorService 接口继承了Executor 接口,是它的子接口;
- Executor 接口定义了execute()方法用来接收一个Runnable接口的对象,而ExecutorService接口中的submit()方法可以接受Runnable和Callable接口的对象;
- Executor 中的execute()方法不返回任何结果,ExecutorService的submit()方法可以通过一个Future对象返回运算结果;
- ExecutorService允许客户端提交一个任务,并且还提供用来控制线程池的方法,比如:调用shutDown()方法终止线程池
它们间的执行关系:
分析说明:
- 主线程首先创建实现Runnable或Callable接口的任务对象;
- 工具类Executors可以把一个Runnable对象封装为一个Callable对象,使用如下两种方式:
- Executors.callable(Runnable task)
- Executors.callable(Runnable task,Object resule)。
- 然后可以把Runnable对象直接提交给ExecutorService执行,方法为ExecutorService.execute(Runnable command);
- 或者也可以把Runnable对象或者Callable对象提交给ExecutorService执行,方法为ExecutorService.submit(Runnable task)或ExecutorService.submit(Callable<T> task)。
- 这里需要注意的是如果执行ExecutorService.submit(...),ExecutorService将返回一个实现Future接口的对象(其实就是FutureTask)。
- 当然由于FutureTask实现了Runnable接口,我们也可以直接创建FutureTask,然后提交给ExecutorService执行。
到此Executor框架的主要体系结构我们都介绍完了,我们对此有了大概了解后,下面我们就重点聊聊两个主要的线程池实现类。
2.ThreadPoolExecutor
3. 3种常见的线程池
它们都直接或者间接地通过配置ThreadPoolExecutor来实现自己的功能特性,这个3种线程池分别是FixedThreadPool,CachedThreadPool,ScheduledThreadPool以及SingleThreadExecutor。
Executor框架、ThreadPoolExecutor、3种常见的线程池相关推荐
- 几种常见的线程池及使用场景
为什么要使用线程池? 创建线程和销毁线程的花销是比较大的,这些时间有可能比处理业务的时间还要长.这样频繁的创建线程和销毁线程,再加上业务工作线程,消耗系统资源的时间,可能导致系统资源不足.(我们可以把 ...
- Java之ThreadPoolExcutor和四种常见的线程池
一.ThreadPoolExcutors的作用 java提供了ThreadPoolExcutors来创建一个线程池,我们为什么要用线程池呢? 1.降低资源的消耗:通过重复利用已经创建好的线程降低线程的 ...
- Java多线程学习七:线程池的 4 种拒绝策略和 6 种常见的线程池
以便在必要的时候按照我们的策略来拒绝任务,那么拒绝任务的时机是什么呢?线程池会在以下两种情况下会拒绝新提交的任务. 第一种情况是当我们调用 shutdown 等方法关闭线程池后,即便此时可能线程池内部 ...
- UNIX(多线程):22---几种常见的线程池
常见线程池 1.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行. 从构造方法 ...
- [并发编程] - Executor框架#ThreadPoolExecutor源码解读02
文章目录 Pre 线程池的具体实现 线程池的创建 参数解读 corePoolSize maximumPoolSize keepAliveTime unit workQueue threadFactor ...
- [并发编程] - Executor框架#ThreadPoolExecutor源码解读01
文章目录 Pre Thread Java线程与OS线程 生命状态 状态切换 线程池 why use case Advantage Executor框架 ThreadPoolExecutor 源码分析 ...
- [并发编程] - Executor框架#ThreadPoolExecutor源码解读03
文章目录 Pre execute源码分析 addWorker()解读 Worker解读 Pre [并发编程] - Executor框架#ThreadPoolExecutor源码解读02 说了一堆结论性 ...
- 解析ThreadPoolExecutor类是如何保证线程池正确运行的
摘要:对于线程池的核心类ThreadPoolExecutor来说,有哪些重要的属性和内部类为线程池的正确运行提供重要的保障呢? 本文分享自华为云社区<[高并发]通过源码深度解析ThreadPoo ...
- 多线程—线程池Executor框架及四种常用线程池
池化技术应用:线程池.数据库连接池.http连接池等等. 池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率. 使用线程池的好处: 降低资源消耗:通过重复利用已创建的线程降低线程创建和 ...
最新文章
- 大公司为什么都有API网关?没你想的那么简单!
- PyQt5之QThread线程模块
- (译)如何用命令行在windows Azure上安装负载平衡的web Farm虚拟机(linux或其他)...
- CentOS7安装iptables防火墙的方法
- ubuntu16.04 安装docker-ce,解决libltdl7版本过低的问题
- sam服务器是什么_使用SAM CLI将机器学习模型部署到无服务器后端
- xMenuTools(超实用右键菜单工具) v7.6
- 中移M5311-NBIOT-OPENCPU开发-HTTP串口收发器
- java编译异常有哪些_编译时JAVA最常见的错误有哪些
- python+selenium笔记(一):元素定位方法
- android语音控制歌曲播放,Amazon Music应用程序已支持Alexa语音控制歌曲播放
- stm32f10x系列.s汇编启动文件
- 深度强化学习笔记(一)——深度强化学习简述
- 算法与数据结构(基于C语言)中线性表的快速排序快速查找
- IntelliJ IDEA自带接口测试工具
- 深度学习 黑白图片 着色
- LOI2504 [HAOI2006]聪明的猴子
- pgsql 筛选中文字符正则_PostGreSql 判断字符串中是否有中文的案例
- Mac苹果系列的安全基线(包括主机和操作系统等)+checklist
- 自动化测试之:python+unittest+selenium
热门文章
- Ansible-playbook简单应用的几个实例
- HttpClient 讲解 (2) 项目封装
- 大容量磁盘分区表、文件系统、分区工具的选择
- 如何防止SQL注入 http://zhangzhaoaaa.iteye.com/blog/1975932
- linux 管道和重定向
- 【tensorflow】 GPU 显存分配设置
- elementui el-drawer去除自带黑色边框、允许滚动(亲测有效)
- 安装CM 6.3.1和CDH 6.3.2
- 【收藏】wsl2 出现 Vmmem内存占用过大问题解决
- helm values使用示例:变量定义及使用