首页 > 其他分享 >线程池-常见问题

线程池-常见问题

时间:2023-11-23 23:48:11浏览次数:33  
标签:常见问题 任务 死锁 线程 多线程 等待 资源

尽管线程池对于构建多线程应用是个很强大的机制,但它也不是没有缺点的。使用线程池构建的应用会面临其他多线程应用所面对的一样的并发风险,比如同步错误和死锁,此外线程池还有其他的一些特有缺陷,比如 线程池-关联 死锁,资源不足,还有线程泄漏。 

死锁

任何多线程应用都会面临死锁的风险。彼此双方都在等待一个事件,而这个事件只能有对方提供,这样一对进程或者线程我们称之为死锁。死锁最简单的情况是线程 A 持有了对象 X 的独占锁,线程 A 在等待对象 Y 的锁,而线程 B 恰恰持有了对象 Y 的独占锁,线程 B 在等待对象 X 的锁。除非有某种办法能够打破这种锁等待(Java 锁机制不能支持这个),否则的话这一对死锁线程将会永久地等待下去。 
既然死锁是所有多线程编程都将面临的风险,线程池为我们引入了另一种死锁:线程池中所有线程都在阻塞等待队列中另一个任务的执行结果,但是另一个任务无法得到执行,因为池中压根儿就没用空闲的可用线程。这种情况在线程池用于一些相互影响对象的模拟实现中可能会出现,这些模拟对象彼此发送查询然后作为任务队列进行执行,发起查询的对象同步等待响应。 

资源不足

线程池的优点之一是他们在大多数情况下比其他的调度机制具备更好的性能,比如我们上面所讨论的那几种。但这个取决于你有没有恰当地配置了线程池大小。线程占用大量的资源,包括内存和其他系统资源。除了线程对象所必须的内存之外,每个线程还需要两个执行调用栈,这个栈可能会很大。此外,JVM 可能还会为每个 Java 线程创建一个本地线程,这样将会占用额外的系统资源。最后,虽然线程之间切换的调度开销很小,大量的线程上下文切换也会影响到你的应用性能。 
如果线程池过大的话,这些众多线程所消耗的资源将会明显影响到系统性能。时间会浪费在线程之间的切换上,配置有比你实际需要更多的线程会引起资源不足的问题,因为池中线程所占用的资源如果用在其他任务上可能会更高效。除了这些线程本身所使用的资源之外,服务请求时所做的工作可能会需要额外资源,比如 JDBC 连接,套接字,或者文件。这些也是有限的资源,而且对它们进行过高并发请求的话可能会导致失效,比如无法分配一个 JDBC 连接。 

并发错误

线程池以及其他队列机制依赖于 wait() 和 notify() 方法的使用,这可能会变得很棘手。如果编码不当的话,很可能会导致通知丢失,结果就是池中的线程都处于一个空闲的状态,而实际上队列中有任务需要处理。在使用这些工具的时候要打起十二万分的精神;即便是专家在用它们的时候也经常会失误。幸运的是,可以使用一些现成的实现,这些实现久经考验,比如下文将会讨论到的 你无须自行编码 实现的 java.util.concurrent 包。 

线程泄漏

各种各样的线程池中存在的一个重大的危险就是线程泄漏,当一个线程被从线程池中移除去执行一个任务,任务执行结束之后却没有返还给线程池的时候,就会出现这种危险。出现这种情况的一种方式是当任务抛出一个 RuntimeException 或一个 Error 时。如果线程池类没有捕捉到这些,该线程将会傻傻地存在于线程池之中,而线程池的线程数量则会被永久地减一。当这种情况发生的次数足够多的时候,线程池最终将为空(无可用线程),而系统则会瘫痪,因为已经没有线程来处理任务了。 
瘫痪的任务,比如那些永久等待不保证可用资源或者等待已经回家了的用户输入的任务,也可以造成相等于线程泄漏一样的后果。如果一个线程永久地被这样一个任务所占用了的话,它造成的影响和从池中移除是一样的。像这样的任务应该要么给它们一个线程池之外的线程,要么控制一下它们的等待时间。 

请求过载

服务器很可能会被铺天盖地而来的请求所淹没。这种情况下,我们可能并不想让每个进来的请求都放进我们的工作队列,因为等待执行的任务队列也可能会占用过多系统资源并导致资源不足。这时候要做什么就取决于你的决定了,比如你可以通过一个表示服务器暂时太忙的响应来拒绝这些请求。 

标签:常见问题,任务,死锁,线程,多线程,等待,资源
From: https://www.cnblogs.com/nxjblog/p/17852781.html

相关文章

  • Android Studio常见问题的解决
    真机调试显示安装包异常在gradle.properties文件最后面加上这一行代码android.injected.testOnly=false以及选择合适的AGP版本,例如选择7.1.2版本,这个版本号可以在build.gradle文件里面修改。gradle下载缓慢的问题在网络防火墙->允许应用通过防火墙->将AndroidStudio添加......
  • springboot定时任务线程池配置拾遗--利用配置类进行配置
    springboot定时任务线程池配置拾遗--利用配置类进行配置目录springboot定时任务线程池配置拾遗--利用配置类进行配置1springboot自动装配1.1通过TaskSchedulingProperties获取yaml参数1.2TaskSchedulingAutoConfiguration自动配置类根据TaskSchedulingProperties的配置装配线......
  • spring和springboot定时任务线程池配置
    spring和springboot定时任务线程池配置目录spring和springboot定时任务线程池配置1背景2配置2.1命名空间配置2.2yaml配置3参考文档1背景项目有几个新增的月末报表生成定时任务(使用spring内置的TaskScheduler),相关业务人员反馈报表没有及时生成,让我比较疑惑:虽然生成比较耗......
  • 进程、线程的中断切换的过程
    上下文切换指的是内核(操作系统的核心)在CPU上对进程或者线程进行切换进程上下文切换(1)保护被中断进程的处理器现场信息(2)修改被中断进程的进程控制块有关信息,如进程状态等(3)把被中断进程的进程控制块加入有关队列(4)选择下一个占有处理器运行的进程(5)根据被选中进程设置操作系统用......
  • 线程
    目录Thread线程一、线程创建的三种方式方式一:继承Thread类的方式进行实现方式二:实现Runnable接口的方式进行实现方式三:利用Callable接口和Future接口方式实现二、Thread状态三、异步ComletableFuture入门Thread线程视频地址:https://www.bilibili.com/video/BV1LG4y1T7n2/?p=5&......
  • C++11线程传递参数汇总
    一、概述总结C++11线程传递参数:1.传递基本数据类型(int、double)2.传递字符串3.传递结构体4.传递类对象二、代码示例//导入线程头文件#include<thread>//导入std命名空间usingnamespacestd;//传递int类型的参数voidthreadFu......
  • Redis单线程速度快原理
    Redis单线程速度快原理基于内存存储实现我们都知道内存读写是比在磁盘快很多的,Redis基于内存存储实现的数据库,相对于数据存在磁盘的MySQL数据库,省去磁盘I/O的消耗。高效的数据结构数据结构说明:Redis内部采用了一些精细化的数据结构和算法,例如哈希表、跳跃表、压缩列表等,这......
  • iOS信号量造成线程优先级反转
    在并发队列使用信号量会可能会造成线程优先级反转一、在iOS16&XCode14上遇到-使用信号量造成线程优先级反转问题提醒经过查询资料,发现是在XCode14上增加了工具,比如:ThreadPerformanceChecker(XCode14上默认开启的),这个工具会让APP在运行的时候,发现有例如线程优先级反转......
  • 9.9 Windows驱动开发:内核远程线程实现DLL注入
    在笔者上一篇文章《内核RIP劫持实现DLL注入》介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过NtCreateThreadEx这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,NtCreateThreadEx......
  • 线程池-基础篇
    常用线程池Executors提供四种线程池:1.newCachedThreadPool:缓存线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。2.newFixedThreadPool:定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。3.newScheduledThreadPool:计划线程池,支持定时及周期......