JAVA技术分享:消失的线程
很多小伙伴都问过我一个问题,就是任务线程跑着跑着消失了,而且没有任何异常日志。我都是条件反射式的回复,是不是用了线程池的submit提交任务。而且很大几率对方给予肯定答复。
解决方案,很多人都听过不少,下面我就分析一下原因以及最佳实践。
为什么消失
submit这个单词用的真的特别好,特别洋气,虽然可以用execute来提交,但是大部分人都是用的submit。问题也就出在submit上了。
public Future? submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture ftask = newTaskFor(task, null); execute(ftask); return ftask; }
submit也是调用的execute,而且是有Future的返回值的。他把一个Runnable 组装成了一个无返回类型的FutureTask。
FutureTask的run方法与众不同。
public void run() { .... try { Callable c = callable; if (c != null state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { .... } }
可以看到FutureTask的run自己捕获了Throwable 而且没有抛出,线程里的所有代码出了什么错都会被捕获,并且赋值给了成员变量outcome。
最终在get里调用report有一段逻辑可以取出异常
private V report(int s) throws ExecutionException { Object x = outcome; if (s == NORMAL) return (V)x; if (s = CANCELLED) throw new CancellationException(); throw new ExecutionException((Throwable)x); }
最后异常会在get的时候throw。
程序出错,异常被吞掉了,最终展现出业务线程消失的现象。
解决方案
run里自己编码解决异常
自己的代码健壮到一言不合来个大写的try catch 而且一定是Throwable并且要合理的记录 。写这种代码真心累,而且在一些特殊场合才这么干,例如javaagent。搞个探针上去,一堆异常在业务系统上,换谁谁都怕。
future.get()
submit的时候会返回一个Future,我们只要get就可以获取到异常。这个是一个理论可行的方案,这个也只用在有交互的场景,例如出现异常了再次提交任务等等。再交互的场景下,这个方案特别适合。
execute提交
submit最终也调用的execute。execute只能接收参数Runnable。
execute直接把异常给抛出了,就是不怎么优雅的记录。
try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); }
每个work执行的时候虽然也会捕获各种异常,但是最后都throw出来了,也能达到追踪的效果。
自定义线程池
继承线程池然后复写afterExecute(task, thrown);上面也看到了最后会执行这个方法,而且可以优雅的记录日志,以及可以做一些补偿操作再里面。
最佳实践
一般使用线程池都会自己去自定义,毕竟为了区别,我们会自己去写线程工厂去标识自己的线程,而且为了内存估计会调整阻塞队列的类型和大小,在一些压力突增的情况还得控制线程池里最大线程的个数与核心线程的比率,所以线程池的自定义是很有必要的。推荐使用自定义线程池的方式记录日志。并不推荐补偿等逻辑也写在线程池里,对于要补偿的情况推荐future.get()。这里只写异常的处理和补偿即可,日志就不用记录了。
JAVA技术分享:消失的线程的更多相关文章
- JAVA技术专题综述之线程篇(1)
本文详细介绍JAVA技术专题综述之线程篇 编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield( ...
- Java技术分享:如何编写servlet程序
身为计算机专业的我,从接触java至今,已经有七年之久,从最开始的小白到现在的大白,这是一个漫长而曲折的历程. 大学刚接触Java这个学科时,一点儿都不理解java是要干嘛的,只知道学起来肯定不容易, ...
- java 技术分享
http://www.ccblog.cn/99.htm http://www.ccblog.cn/100.htm http://www.ccblog.cn/101.htm http://www.ccb ...
- 最值得收藏的java技术博客(Java篇)
第一个:java_my_life 作者介绍:找不到原作者信息.大概做了翻阅全部是2012年的博客. 博客主要内容:主要内容是关于Java设计模式的一些讲解和学习笔记,在相信对学习设计模式的同学帮助很大 ...
- 爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结
本文由爱奇艺技术团队原创分享,原题<爱奇艺Android客户端启动优化与分析>. 1.引言 互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Andro ...
- 微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)
1.点评 对于IM系统来说,如何做到IM聊天消息离线差异拉取(差异拉取是为了节省流量).消息多端同步.消息顺序保证等,是典型的IM技术难点. 就像即时通讯网整理的以下IM开发干货系列一样: <I ...
- 推荐:7 月份值得一看的 Java 技术干货!
月底了,又到了我们总结这一个月 Java 技术干货的时候了,又到了我们给粉丝免费送书的日子了. 7 月份干货总结 Oracle 发布了一个全栈虚拟机 GraalVM 一文带你深入拆解 Java 虚拟机 ...
- UWA 技术分享连载 转载
技术分享连载1 Q1:Texture占用内存总是双倍,这个是我们自己的问题,还是Unity引擎的机制? Q2:我现在发现两个因素直接影响Overhead,一个是Shader的复杂度,一个是空Updat ...
- 技术分享之AQS——内容提要
1. 背景 最近团队内部技术分享,我做了个关于AQS的分享.ppt中涵盖的部分要点内容,现在整理到博客上. 关于AQS本身的源码解读,可以参考我之前的博文. 2. 要点梳理 下面是一些技术分享的要点梳 ...
随机推荐
- jpa关联映射(一)
开发中常用到数据表的关联(其实很难遇到..),spring-data-jpa(其实是hibernate)提供了一整套十分方便的注解来供我们使用表关联功能. OneToOne OneToMany Man ...
- postgresql----ANY/SOME&&ALL
一.ANY/SOME WHERE expression operator ANY (subquery)WHERE expression operator SOME (subquery) 其实ANY和S ...
- 【css预处理器】------sass的基本语法------【巷子】
001.安装sass 1.删除gem源:gem sources --remove https://rubygems.org/ 2.添加国内源:gem sources -a http://gems.ru ...
- PL/SQL编程基础(四):程序控制(IF,CASE,FOR,LOOP,WHILE LOOP,EXIT,CONTINUE)
程序控制 程序结构有分支结构与循环结构: 分支结构语法:IF.CASE: 循环结构:FOR.WHILE LOOP:先执行再判断,至少执行一次: WHILE LOOP:先判断再执行,如果不满足条件,就不 ...
- How many ways??---hdu2157(矩阵快速幂)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2157 题意:有一个有向图,含有n个节点,m条边,Q个询问,每个询问有 s,t,p,求 s 到 t ...
- java-mybaits-009-mybatis-spring-使用,SqlSessionFactoryBean、事务
一.版本限制 参看地址:http://www.mybatis.org/spring/ 二.使用入门 2.1.pom <dependency> <groupId>org.myba ...
- git-flow工作流程
什么是 git-flow? 一旦安装安装 git-flow,你将会拥有一些扩展命令.这些命令会在一个预定义的顺序下自动执行多个操作.是的,这就是我们的工作流程! git-flow 并不是要替代 Git ...
- springboot的相关信息
Maven的配置:zzp_settings.xml <?xml version="1.0" encoding="UTF-8"?> <setti ...
- HDU:Gauss Fibonacci(矩阵快速幂+二分)
http://acm.hdu.edu.cn/showproblem.php?pid=1588 Problem Description Without expecting, Angel replied ...
- 前端基础(JavaScript)
JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.( ...