java使用默认线程池踩过的坑(二)

【java】死锁产生分析与检测分析工具 最近在看了一些关于多线程死锁分析的博客,在死锁的分析方面有了一点自己的经验,下面将它总结记录下来。 1. 死锁简介 1.1 死锁的产生 1.2 线程 1.3 锁 2. 死锁举例 3. 死锁分析 3.1 VisualVM简介 3.2 VisualVM中插件安装 3.3 线程监视 3.4线程dump分析 3.5 Dump内容分析 3.6 利用Thread Dumps Anal... 阅读详情

云智慧(北京)科技有限公司 陈鑫

是的,一个线程不能够启动两次。那么它是怎么判断的呢?
public synchronized void start() {
/**
* A zero status valuecorresponds to state “NEW”. 0对应的是state NEW
*/
if (threadStatus!= 0) //如果不是NEW state,就直接抛出异常!
throw newIllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0(); // 启动线程的native方法
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch(Throwable ignore) {
}
}
}
恩,只有是NEW状态才能够调用native方法启动一个线程。好吧,到这里了,就普及也自补一下jvm里的线程状态:
所有的线程状态::
l NEW —— 还没有启动过
l RUNNABLE —— 正在jvm上运行着
l BLOCKED —— 正在等待锁/信号量被释放
l WAITING —— 等待其他某个线程的某个特定动作
l TIMED_WAITING —— A thread that iswaiting for another thread to perform an action for up to a specified waitingtime is in this state.
l TERMINATED —— 退出,停止
线程在某个时间点上只可能存在一种状态,这些状态是jvm里的,并不反映操作系统线程的状态。查一下Thread的API,没有对其状态进行修改的API。那么这条路是不通的吗?
仔细考虑一下……
如果把任务做成Runnable实现类,然后在把这个实现类丢进线程池调度器之前,利用此Runnable构造一个Thread,是不是这个Thread对象就能够控制这个runnable对象,进而控制在线程池中运行着的task了呢?非也!让我们看看Thread和ThreadPoolExecutor对Runnable的处理吧。
Thread
/* What will berun. */
private Runnabletarget;
结合上面的start()方法,很容易猜出,start0()会把target弄成一个线程来进行运行。
ThreadPoolExecutor
public void execute(Runnable command){
if (command== null)
thrownew NullPointerException();
int c =ctl.get();
if(workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c =ctl.get();
}
if(isRunning(c) && workQueue.offer(command)) {
intrecheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command);
else if(workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}

private boolean addWorker(RunnablefirstTask, boolean core) {
…
booleanworkerStarted = false;
booleanworkerAdded = false;
Worker w =null;
try {
finalReentrantLock mainLock = this.mainLock;
w = newWorker(firstTask);
finalThread t = w.thread;
if (t!= null) {
mainLock.lock();
try{
int c = ctl.get();
int rs = runStateOf(c);

               if (rs < SHUTDOWN ||
                   (rs == SHUTDOWN && firstTask == null)) {
                   if (t.isAlive()) // precheck that t is startable
                        throw newIllegalThreadStateException();

workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize =s;
workerAdded = true;
}
}finally {
mainLock.unlock();
}
if(workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (!workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
那么Worker又是怎样的呢?
Worker
private final class Worker
extendsAbstractQueuedSynchronizer
implementsRunnable
{
finalThread thread;
RunnablefirstTask;
volatilelong completedTasks;
Worker(Runnable firstTask) {
setState(-1); //调用runWorker之前不可以interrupt
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public voidrun() {
runWorker(this);
}
……
…….
voidinterruptIfStarted() {
Threadt;
if(getState() >= 0 && (t = thread) != null &&!t.isInterrupted()) {
try{
t.interrupt();
}catch (SecurityException ignore) {
}
}
}
}
可见worker里既包装了Runnable对象——task,又包装了一个Thread对象——以自己作为初始化参数,因为worker也是Runnable对象。然后对外提供了运行与停止接口,run()和interruptIfStarted()。回顾上面使用Thread的例子不禁有了新的领悟,我们把一个Thread对象交给ThreadPoolExecutor执行后,实际的调用是对Thread(FileTask())对象,我们暂时称之为workerWrapper。那么我们在池外进行FileTask.interrupt()操作影响的是FileTask对象,而不是workerWrapper。所以可能上面对于start()方法二次调用不是特别适当。更恰当的应该是在fileTask.interrupt()的时候就跑出异常,因为从来没有对fileTask对象执行过start()方法,这时候去interrupt就会出现错误。具体如下图:
无
分析到此,我们已经明确除了调用ThreadPoolExecutor了的interruptWorkers()方法别无其他途径操作这些worker了。
private void interruptWorkers() {
finalReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for(Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}

Unity Shader学习笔记/Urp/水墨风效果 Unity Shader学习 阅读详情

相关推荐

Linux文件操作四剑客

① /^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$/ // 年-月-日 yyyy-MM-dd / yy-MM-dd 格式。⑥“^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$” //正浮点数。

wuds_158的博客 1609

服务器跑着跑着线程池都挂了java.lang.Thread.State: TIMED_WAITING (parking)

java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000000af662cf0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.

mysql数据库 innodb存储引擎怎么创建好索引 2万+

HC32 CAN通信

qqa

zhaopenglihui的博客 5433

3、AsyncTool框架原理源码解析

本文是专栏《AsyncTool框架原理源码解析》系列的第三篇文章《AsyncTool框架原理源码解析》,从代码实战进入到源码分析。从项目包结构、类UML关系结构、调用流程再到和等多个功能接口层层递进,逐个击破。掌握原理,知其然而知其所以然。专栏《AsyncTool框架原理源码解析》共有 5篇 文章,由浅入深,从实战使用再到源码、原理分析,包括但不仅局限于思考和总结,最后分享下我为开源项目贡献代码。以下是《专栏目录》:类很少,核心代码就在WorkerWrapper和Acync类当中。整个框架的调用流程特别简单

真正的大师,永远怀着一颗学徒的❤ 3564

淘晶驰串口屏自定义协议实战:5分钟搞定苹果时钟通信(附完整代码)

本文详细介绍了如何使用淘晶驰串口屏自定义通信协议快速实现苹果风格时钟的通信功能。通过精简的协议设计和完整的代码示例,开发者可以在5分钟内完成从硬件连接到软件实现的整个过程,适用于嵌入式开发中的高效通信需求。

weixin_29184371的博客 323

5-DOF机械臂课程设计(一)之正逆运动学

文章目录基本要求基本概念关节坐标系的建立正运动学求解DH参数表的建立逆运动学求解多解下解的选取源码下载后续 基本要求 ​ 开发上位机程序,要求有良好的界面,能提供关节空间下和笛卡尔坐 标下表示的目标位姿点和中间若干经过点的输入功能,进行轨迹规划, 并控制机械臂沿轨迹运动,最终完成目标抓取的任务。 基本概念 连杆长度 :2个相邻关节轴线之间的距离 连杆扭角 :2个相邻关节轴线之间的角度 连杆偏距 :2个关节坐标系的X轴之间的距离 关节角度 :关节变量 计算时需要加初始角度偏移 关节坐标系的建立 ​ 根据《机

Rosen的博客 5855

研究一款 Java 线程编排并行框架-asyncTool

如果有复杂场景,可以参考这个框架,但一定要熟知这个框架的特性,比如超时快速失败等场景是否接受;我要执行 TaskC,则先执行 TaskA 和 TaskB,然后才能执行 TaskC,最后再执行 TaskD。“解决任意的多线程并行、串行、阻塞、依赖、回调的并行框架,可以任意组合各线程的执行顺序,带全链路执行结果回调。因此,不管从 TaskC 作为入口,还是 TaskD 作为入口,它的执行结果都是一致的。最后,如果有后续的任务依赖于当前任务的完成,WorkerWrapper 将触发下一个任务的执行。

uzong 3202

Temporal Anti-Aliasing(时域抗锯齿TAA)

首先说一下走样:一般分为时域走样(如旋转车轮)和空域走样(锯齿),但在 TAA 技术是采用时域相关叠加混合技术来解决空域走样的问题。 简单看一下空域抗锯齿 (Spatial Anti-Aliasing, SAA)相关技术,最普及的莫过于 MSAA,被各大渲染引擎采用,但是 MSAA 并不适用于延迟渲染 (Deferred Rendering),随之出现了很多基于形态学的后处理抗锯齿技术,如 MLAA,FXAA,SMAA 等(具体看参见图形_反走样技术总结相关介绍),虽然他们表现良好且支持延迟渲染,但是都会面

qq_35312463的博客 1万+

聊聊tunny的workerWrapper

序 本文主要研究一下tunny的workerWrapper workerWrapper type workerWrapper struct { worker Worker interruptChan chan struct{} // reqChan is NOT owned by this type, it is used to send requests for work. reqChan chan<- workRequest // closeChan can be cl

go4it 417

星宸科技SSD20x/SSD21X应用层DEMO实战指南:从入门到深度定制

本文详细介绍了星宸科技SSD20x/SSD21X系列芯片的应用层DEMO开发实战,从基础环境搭建到深度定制开发。内容涵盖DEMO资源获取、核心功能实现、第三方库集成以及性能优化技巧,帮助开发者快速掌握智能显示和多媒体处理应用的开发方法。特别适合嵌入式开发者在智能家居、工业控制等场景中应用。

weixin_42524226的博客 267

FOC实战笔记:RC吸收电路的设计考量与参数调优

本文深入探讨了FOC驱动器中RC吸收电路的设计与调优。针对MOS管开关过程中的电压尖峰问题,详细阐述了RC电路的钳位与能量吸收原理,并提供了从参数计算、实验调试到布局布线的完整实战指南,旨在帮助工程师有效提升系统可靠性与稳定性。

weixin_29219539的博客 273

Java 并发编程避坑指南:线程池踩坑现场+救场秘籍

在并发编程中,线程池是提高性能和资源管理的核心工具之一。但在使用线程池的过程中,如果不注意细节,很容易踩到一些坑,导致程序性能下降或甚至崩溃。今天,我们就来为你揭秘 Java 线程池的常见坑,教你如何规避这些问题,帮助你成为线程池的高手!Java 中的线程池可以大幅度提高并发编程的效率,但也伴随着一定的陷阱。了解这些常见的坑并采取合适的措施进行规避,可以让你的多线程编程更加稳健、有效。在实际开发中,合理配置线程池、优化线程管理,才能确保高效和稳定的执行!

龚小帅的博客 1050

luks-磁盘加密工具

linux磁盘加密配置工具及步骤详解

zdd56789的博客 120

记CompletableFuture默认线程池踩坑经历

在Java8开始引入了全新的类,它是Future接口的一个实现类。也就是在Future接口的基础上,额外封装提供了一些执行方法,用来解决Future使用场景中的一些不足,对处理能力提供了支持。当我们需要进行异步处理的时候,我们可以通过方法,传入一个具体的要执行的处理逻辑函数,这样就轻松的完成了CompletableFuture的创建与触发执行。相信大部分都用过这种方法执行过异步任务。

不懂的博客 1554

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

生产问题之CompletableFuture默认线程池踩坑,请务必自定义线程池

CompletableFuture是否使用默认线程池的依据,和机器的CPU核心数有关。当CPU核心数-1大于1时,才会使用默认的线程池,否则将会为每个CompletableFuture的任务创建一个新线程去执行。

java_2017_csdn的博客 4910

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

用线程池,注意避坑

线程池是 Java 中处理多线程的强大工具,但它不仅仅是“直接用就完事”的工具。很多小伙伴在用线程池时,因为配置不当或忽略细节,踩过许多坑。今天跟大家一起聊聊线程池中容易踩的 10 个坑,以及如何避免这些坑,希望对你会有所帮助。线程池是强大的工具,但如果我们日常工作中用得不好也非常容易踩坑。这篇文章通过实际代码示例,我们可以清楚看到线程池的问题所在及改进方法。希望这些内容能帮你避免踩坑,写出高质量的线程池代码!线程池用得好,效率杠杠的;用得不好,程序天天崩!

kangbin825的专栏 907

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

java踩坑之线程池

java踩坑之线程池 就有前几天刚完成的大型对比时使用到了线程池,对于线程池,我想我有好多踩过的坑的经历,这也就是所说的经验吧,我想通过这篇文章,将我所踩过的坑,都记录下来. 坑1-newFixedThreadPool 程序问题演示: 这是jdk提供的一个默认线程线程池的实现。创建一组固定大小的线程池,来运行任务。当时这个任务是用来运行后台的异步发送通知任务。每秒大约100个发送量,高峰时段大约500个发送量,量并不大。但有一天通知服务突然宕机了,而我们服务调用超时的时间是2分钟,结果就导致我们的服务出现了

bug_null的博客 1204

你是否傻傻分不清SpringBoot默认线程池和内置Tomcat线程池?

在Java应用程序中,线程池是一种用于管理和重用线程的机制。线程池可以显著提高多线程应用程序的性能,避免不必要的线程创建和销毁开销,同时有效控制并发线程数量,防止系统资源被耗尽。对于SpringBoot程序,我们知道它是会有一个内置的Tomcat,但是我自己之前一直对于SpringBoot默认线程池和SpringBoot内置Tomcat线程池概念不是很清晰,很容易混淆,甚至以为它们就是一个东西,经过这次深入了解以后,发现两个完全是不同的东西,接下来跟我一起探索吧~我们可以通过在应用的配置文件(如或。

Apple_Boy的博客 7670

Java线程池的隐藏坑

使用线程池时,如果没有给线程池一个有意义的名称,将不好排查回溯问题。这不算一个坑吧,只能说给以后排查埋坑,因为个人觉得这个还是比较重要的。/***/System.out.println("关注公众号:捡田螺的小男孩");});可以发现,默认打印的线程池名字是pool-1-thread-1,如果排查问题起来,并不友好。因此建议大家给自己线程池自定义个容易识别的名字。System.out.println("关注公众号:捡田螺的小男孩");});

dcp666的博客 714

线程池使用的10个坑(二)

使用线程池时,如果没有给线程池一个有意义的名称,将不好排查回溯问题。这不算一个坑吧,只能说给以后排查埋坑,哈哈。我还是单独把它放出来算一个点,因为个人觉得这个还是比较重要的。/*** 关注公众号:捡田螺的小男孩*/System.out.println("关注公众号:捡田螺的小男孩");});}}复制代码关注公众号:捡田螺的小男孩复制代码可以发现,默认打印的线程池名字是,如果排查问题起来,并不友好。因此建议大家给自己线程池自定义个容易识别的名字。其实用。...

ch98000的博客 856

java使用默认线程池踩过的坑(一)

云智慧(北京)科技有限公司 陈鑫 场景 一个调度器,两个调度任务,分别处理两个目录下的txt文件,某个调度任务应对某些复杂问题的时候会持续特别长的时间,甚至有一直阻塞的可能。我们需要一个manager来管理这些task,当这个task的上一次执行时间距离现在超过5个调度周期的时候,就直接停掉这个线程,然后再重启它,保证两个目标目录下没有待处理的txt文件堆积。问题 直接使用java默认的线程

cloudwiseAPM的专栏 1130

Java 线程池踩坑记:从 OOM 到性能飙升的 5 个优化技巧

《高并发场景下线程池参数配置实战》摘要:本文针对ThreadPoolExecutor使用中的常见误区,结合电商秒杀场景,深入解析线程池参数配置要点。指出无界队列和过大maximumPoolSize易引发OOM问题,推荐采用CPU核心数*2确定核心线程数,使用有界队列配合CallerRunsPolicy拒绝策略实现限流。文章提供自定义线程工厂、实时监控方案,并介绍动态调整参数的进阶优化方法。最后强调拒绝策略选择、避免使用Executors工具类等关键避坑点,为高并发场景提供可落地的线程池优化方案。

weixin_60786293的博客 522

Java中默认四种线程池使用分析

Java定义了Executor接口并在该接口中定义了execute( )用于执行一个线程任务,然后通过ExecutorService实现Executor接口并执行具体的线程操作。ExecutorService接口有多个实现类可用于创建不同的线程池。 newCachedThreadPool newCachedThreadPool用于创建衣蛾缓存线程池。之所以叫缓存线程池,是因为它在创建新线程时,如果有可重用的线程,则重用他们,否则重新创建一个新的线程并将其添加到线程池中。对于执行时间很短的任务惹眼,new

蜗牛学习笔记 1680

在java中使用线程池会有哪些坑?

在Java中使用线程池时,确实存在一些常见的陷阱和坑。

qq_43345619的博客 894

Java线程池深度解析(二):线程池类型与任务队列选择指南

在线程池第一篇章的学习中,我们复习了线程池的基本参数和使用以及优雅关停,由于篇幅原因还是有很多细节没有展开。现在提出几个问题来开始本次线程池的学习之旅:1.一共有几种线程池,区别是什么2.关于线程池的workQueue有哪些,怎么选择?CPU密集型• 线程数 = CPU核心数 + 1(容量适度)I/O密集型• 线程数 = 2 × CPU核心数(有界)或混合型任务• 拆分为CPU密集型队列 + I/O密集型队列• 使用区分优先级通用原则•永远为队列设置合理上限•。

weixin_42347876的博客 2610
上一篇: java使用默认线程池踩过的坑(一)
下一篇: java使用默认线程池踩过的坑(三)
cloudwiseAPM
博客等级 码龄12年 23粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值