Java多线程系列(五):线程池的实现原理、优点与风险、以及四种线程池实现

为什么需要线程池

我们有两种常见的创建线程的方法,一种是继承Thread类,一种是实现Runnable的接口,Thread类其实也是实现了Runnable接口。但是我们创建这两种线程在运行结束后都会被虚拟机销毁,如果线程数量多的话,频繁的创建和销毁线程会大大浪费时间和效率,更重要的是浪费内存。那么有没有一种方法能让线程运行完后不立即销毁,而是让线程重复使用,继续执行其他的任务哪?

这就是线程池的由来,很好的解决线程的重复利用,避免重复开销。

线程池的优点

1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。

2、可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。

线程池的风险

虽然线程池是构建多线程应用程序的强大机制,但使用它并不是没有风险的。用线程池构建的应用程序容易遭受任何其它多线程应用程序容易遭受的所有并发风险,诸如同步错误和死锁,它还容易遭受特定于线程池的少数其它风险,诸如与池有关的死锁、资源不足和线程泄漏。

1.死锁

任何多线程应用程序都有死锁风险。当一组进程或线程中的每一个都在等待一个只有该组中另一个进程才能引起的事件时,我们就说这组进程或线程 死锁了。死锁的最简单情形是:线程 A 持有对象 X 的独占锁,并且在等待对象 Y 的锁,而线程 B 持有对象 Y 的独占锁,却在等待对象 X 的锁。除非有某种方法来打破对锁的等待(Java 锁定不支持这种方法),否则死锁的线程将永远等下去。

2.资源不足

线程池的一个优点在于:相对于其它替代调度机制(有些我们已经讨论过)而言,它们通常执行得很好。但只有恰当地调整了线程池大小时才是这样的。

线程消耗包括内存和其它系统资源在内的大量资源。除了
Thread 对象所需的内存之外,每个线程都需要两个可能很大的执行调用堆栈。除此以外,JVM 可能会为每个 Java
线程创建一个本机线程,这些本机线程将消耗额外的系统资源。最后,虽然线程之间切换的调度开销很小,但如果有很多线程,环境切换也可能严重地影响程序的性能。

如果线程池太大,那么被那些线程消耗的资源可能严重地影响系统性能。在线程之间进行切换将会浪费时间,而且使用超出比您实际需要的线程可能会引起资源匮乏问题,因为池线程正在消耗一些资源,而这些资源可能会被其它任务更有效地利用。

除了线程自身所使用的资源以外,服务请求时所做的工作可能需要其它资源,例如 JDBC 连接、套接字或文件,这些也都是有限资源,有太多的并发请求也可能引起失效,例如不能分配 JDBC 连接。

3.并发错误

线程池和其它排队机制依靠使用
wait() 和 notify()
方法,这两个方法都难于使用。如果编码不正确,那么可能丢失通知,导致线程保持空闲状态,尽管队列中有工作要处理。使用这些方法时,必须格外小心;即便是专家也可能在它们上面出错。而最好使用现有的、已经知道能工作的实现,例如在
util.concurrent 包。

4.线程泄漏

各种类型的线程池中一个严重的风险是线程泄漏,当从池中除去一个线程以执行一项任务,而在任务完成后该线程却没有返回池时,会发生这种情况。发生线程泄漏的一种情形出现在任务抛出一个 RuntimeException 或一个 Error 时。

如果池类没有捕捉到它们,那么线程只会退出而线程池的大小将会永久减少一个。当这种情况发生的次数足够多时,线程池最终就为空,而且系统将停止,因为没有可用的线程来处理任务。

5.请求过载

仅仅是请求就压垮了服务器,这种情况是可能的。在这种情形下,我们可能不想将每个到来的请求都排队到我们的工作队列,因为排在队列中等待执行的任务可能会消耗太多的系统资源并引起资源缺乏。在这种情形下决定如何做取决于您自己;在某些情况下,您可以简单地抛弃请求,依靠更高级别的协议稍后重试请求,您也可以用一个指出服务器暂时很忙的响应来拒绝请求。

线程池的实现原理

线程池

Java多线程系列(五):线程池的实现原理、优点与风险、以及四种线程池实现

1.线程池状态

线程池和线程一样拥有自己的状态,在ThreadPoolExecutor类中定义了一个volatile变量runState来表示线程池的状态,线程池有四种状态,分别为RUNNING、SHURDOWN、STOP、TERMINATED。

  • 线程池创建后处于RUNNING状态。
  • 调用shutdown后处于SHUTDOWN状态,线程池不能接受新的任务,会等待缓冲队列的任务完成。
  • 调用shutdownNow后处于STOP状态,线程池不能接受新的任务,并尝试终止正在执行的任务。
  • 当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态。

线程池原理:预先启动一些线程,线程无限循环从任务队列中获取一个任务进行执行,直到线程池被关闭。如果某个线程因为执行某个任务发生异常而终止,那么重新创建一个新的线程而已,如此反复。

2.线程池的处理流程

1、判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。

2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。

3、判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

Java多线程系列(五):线程池的实现原理、优点与风险、以及四种线程池实现

配置线程池大小配置

一般需要根据任务的类型来配置线程池大小:

如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1

如果是IO密集型任务,参考值可以设置为2*NCPU

当然,这只是一个参考值,具体的设置还需要根据实际情况进行调整,比如可以先将线程池大小设置为参考值,再观察任务运行情况和系统负载、资源利用率来进行适当调整。

Java提供的四种线程池实现

(1)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

(2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

(3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

(4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。


以上就是线程池的详细介绍,后续将详细讲解四种线程池的具体实现。


money.jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480119.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文浅尝 | 面向单关系事实问题的中文问答模型

来源:NLPCC 2017论文下载地址:http://tcci.ccf.org.cn/conference/2017/papers/2003.pdf动机开放领域的QA问题是一个被广泛研究的问题,而且目前这个问题并没有被很好地解决。在中文领域,相关的数据集并不多。而NLPCC开放了一个KBQ…

玩转算法值面试-第五章 -在链表中穿针引线

5-123 数组中可以随机访问,相反链表就不行 leetcode:206 反转一个链表,链表如果没有特别声明,则节点的值不发生改变 一共需要三个指针:current指向当前需要处理的指针 next指向当前需要处理的元素的下一个元素的指针…

论文笔记(SocialGCN: An Efficient Graph Convolutional Network based Model for Social Recommendation)

一个有效的基于图卷积神经网络的社交推荐模型 原文链接:SocialGCN: An Efficient Graph Convolutional Network based Model for Social Recommendation, arxiv 原理:在用户-项交互图上应用GNN来学习用户向量的表示,用户向量和项向量内积预测…

POJ 1753 Flip Game(回溯)

文章目录1. 题目1.1 题目链接1.2 题目大意1.3 解题思路2. 代码2.1 Wrong Answer代码2.2 Accepted代码1. 题目 1.1 题目链接 http://poj.org/problem?id1753 1.2 题目大意 一个黑白棋子的棋盘,一个反过来周围四个也跟着反过来(如果存在的话),颜色取反…

他读书时挣了五十万,找工作时收获阿里腾讯快手等ssp offer

今天介绍一位dalao,他之前在中科院获取了计算机硕士学位,现在是一名大厂的算法工程师。大多数人的学生生活,是在枯燥的课程和任务中度过的,但他却有所不同,乐于折腾,收获了不一样的精彩。他喜欢去公司实习&…

Java多线程系列(三):Java线程池的使用方式,及核心运行原理

之前谈过多线程相关的4种常用Java线程锁的特点,性能比较、使用场景,今天主要分享线程池相关的内容,这些都是属于Java面试的必考点。 为什么需要线程池 java中为了提高并发度,可以使用多线程共同执行,但是如果有大量线程短时间之内…

论文浅尝 | 图神经网络综述:方法及应用

论文链接:https://arxiv.org/pdf/1812.08434.pdfGNN相关论文列表链接:https://github.com/thunlp/GNNPapers近日,清华刘知远老师组在arXiv上发表了一篇关于图神经网络的综述,本次论文浅尝在分享这篇论文的基础上,对图神…

论文笔记(Social Attentional Memory Network:Modeling Aspect- and Friend-level Differences in Recom-)

社交注意记忆网络:模拟面级别和朋友级别的区别 原文链接:Social Attentional Memory Network: Modeling Aspect- and Friend-Level Differences in Recommendation, WSDM’19 1. 摘要 社会中的连接有助于提升推荐系统的性能,但是&#xff…

玩转算法之面试-第六章(栈和队列)

leetcode 20 此时栈顶的左括号和当前遍历的右括号匹配,故将左括号从栈顶pop出。 leetcode 150: leetcode 71 栈和递归的关系 递归算法:二叉树中的算法 、二叉树的前序遍历,中序遍历,后序遍历 前序遍历代码&am…

POJ 1321 棋盘问题(回溯)

文章目录1. 题目1.1 题目链接1.2 题目大意1.3 解题思路2. 代码2.1 Accepted 代码1. 题目 1.1 题目链接 http://poj.org/problem?id1321 1.2 题目大意 在一个给定形状的棋盘(只能在#号的位置摆放)上面摆放棋子,棋子没有区别。要求摆放时任…

Java多线程系列(二):线程的五大状态,以及线程之间的通信与协作

在Java面试的时候,经常会问到Java并发编程相关的多线程、线程池、线程锁、线程通信等面试必考点,比如: Java并发编程系列:Java线程池的使用方式,核心运行原理、以及注意事项 Java并发编程系列:4种常用Jav…

负样本为王:评Facebook的向量召回算法

星标/置顶小屋,带你解锁最萌最前沿的NLP、搜索与推荐技术有人的地方就会有江湖,就会有鄙视链存在,推荐系统中也不例外。排序、召回,尽管只是革命分工不同,但是我感觉待遇还是相差蛮大的排序排序,特别是精排…

论文浅尝 | TEQUILA: 一种面向时间信息的知识问答方法

来源:CIKM’18链接:http://delivery.acm.org/10.1145/3270000/3269247/p1807-jia.pdf?ip223.3.116.39&id3269247&accACTIVE%20SERVICE&keyBF85BBA5741FDC6E%2EEEBE655830483280%2E4D4702B0C3E38B35%2E4D4702B0C3E38B35&__acm__15478819…

京东2020算法工程师0824笔试题整理

代码题: 1:开心消消乐: #include #include #include #include #include #include #include #define ll long long #define inf 0x3f3f3f3f #define Max 1001 using namespace std; int dir[4][2]{{-1,0},{1,0},{0,-1},{0,1}}; string …

论文笔记(eTrust: Understanding Trust Evolution in an Online World)

eTrust:理解线上信任进化 原文链接:eTrust: Understanding Trust Evolution in an Online World, KDD’12 原理:用户偏好与项的向量内积 用户与朋友相似度权重*朋友对项的时间衰减评分用户对项的评分 摘要 大部分关于线上信任的研究都假设…

技术动态 | 67 亿美金搞个图,创建知识图谱的成本有多高你知道吗?

OpenKG 祝各位读者元宵节快乐!本文转载自公众号:机器之心。选自ISWC作者:Baptiste Rocca参与:思源、李亚洲我们知道强大的深度模型需要很多计算力,那你知道创建一个知识图谱的成本到底是多少吗?德国 Mannhe…

Attention模型:我的注意力跟你们人类不一样

星标/置顶小屋,带你解锁最萌最前沿的NLP、搜索与推荐技术文 | 小轶背景截至今日,Badanau Attention的原文citation已达1.34w之多。2020年几乎所有主流NLP任务都需要借助attetion来实现。在深度学习全民炼丹的时代,attention是为数不多具有较强…

动态规划算法(Dynamic Programming)之0-1背包问题

文章目录1. 问题引入2. 动态规划求解0-1背包3. 复杂度4. 0-1背包升级版(带价值)5. 0-1背包升级版(带价值)DP解法1. 问题引入 前面讲了0-1背包的回溯解决方法,它是穷举所有可能,复杂度是指数级别的&#xf…

Java多线程系列(一):最全面的Java多线程学习概述

Java并发编程的技能基本涵括以下5方面: 多线程 线程池 线程锁 并发工具类 并发容器 多线程的4种创建方式 继承Thread 实现Runnable接口 实现Callable接口 以及线程池来创建线程 Java线程的生命周期 线程的创建 线程的就绪 线程的运行 线程的阻塞 线程的死…

论文浅尝 | 基于知识库的自然语言理解 01#

本文转载自公众号:知识工场。罗康琦,上海交通大学计算机系2019届博士,研究方向为自然语义理解和知识图谱。2012年获得华中科技大学软件工程学士学位,现就职于京东数据科学实验室(Data Science Lab)。他曾在…