很多小伙伴都问过我一个问题,就是任务线程跑着跑着消失了,而且没有任何异常日志。我都是条件反射式的回复,是不是用了线程池的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技术分享:消失的线程的更多相关文章

  1. JAVA技术专题综述之线程篇(1)

    本文详细介绍JAVA技术专题综述之线程篇 编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield( ...

  2. Java技术分享:如何编写servlet程序

    身为计算机专业的我,从接触java至今,已经有七年之久,从最开始的小白到现在的大白,这是一个漫长而曲折的历程. 大学刚接触Java这个学科时,一点儿都不理解java是要干嘛的,只知道学起来肯定不容易, ...

  3. java 技术分享

    http://www.ccblog.cn/99.htm http://www.ccblog.cn/100.htm http://www.ccblog.cn/101.htm http://www.ccb ...

  4. 最值得收藏的java技术博客(Java篇)

    第一个:java_my_life 作者介绍:找不到原作者信息.大概做了翻阅全部是2012年的博客. 博客主要内容:主要内容是关于Java设计模式的一些讲解和学习笔记,在相信对学习设计模式的同学帮助很大 ...

  5. 爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结

    本文由爱奇艺技术团队原创分享,原题<爱奇艺Android客户端启动优化与分析>. 1.引言 互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Andro ...

  6. 微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

    1.点评 对于IM系统来说,如何做到IM聊天消息离线差异拉取(差异拉取是为了节省流量).消息多端同步.消息顺序保证等,是典型的IM技术难点. 就像即时通讯网整理的以下IM开发干货系列一样: <I ...

  7. 推荐:7 月份值得一看的 Java 技术干货!

    月底了,又到了我们总结这一个月 Java 技术干货的时候了,又到了我们给粉丝免费送书的日子了. 7 月份干货总结 Oracle 发布了一个全栈虚拟机 GraalVM 一文带你深入拆解 Java 虚拟机 ...

  8. UWA 技术分享连载 转载

    技术分享连载1 Q1:Texture占用内存总是双倍,这个是我们自己的问题,还是Unity引擎的机制? Q2:我现在发现两个因素直接影响Overhead,一个是Shader的复杂度,一个是空Updat ...

  9. 技术分享之AQS——内容提要

    1. 背景 最近团队内部技术分享,我做了个关于AQS的分享.ppt中涵盖的部分要点内容,现在整理到博客上. 关于AQS本身的源码解读,可以参考我之前的博文. 2. 要点梳理 下面是一些技术分享的要点梳 ...

随机推荐

  1. github(其他类似github)下载到本地配置

    首先是先装完插件,低版本的myeclipse要自己装插件, 如何使window->show view->other找到git 注意是选第二个... 然后next->next-> ...

  2. rest_framework之序列化详解 06

    拿到所有的角色数据 1.urls.py 2.models.py  假设只有3个角色 3.views.py from api import models import json json只能序列化pyt ...

  3. jQuery Ajax 全解析(转载)

    本文地址: jQuery Ajax 全解析 本文作者:QLeelulu 转载请标明出处! jQuery确实是一个挺好的轻量级的JS框架,能帮助我们快速的开发JS应用,并在一定程度上改变了我们写Java ...

  4. pyhton 函数参数,递归函数,高阶函数(一点点笔记)

    '''def test(x,y): print(x) print(y)test(2,y=3)def test(*args):#参数可以是不确定的多个数,接受N个位置参数,转换成元组形式 print(a ...

  5. ZOJ 3537 Cake(凸包判定+区间DP)

    Cake Time Limit: 1 Second Memory Limit: 32768 KB You want to hold a party. Here's a polygon-shaped c ...

  6. 徐州网络赛F-Feature Trace【暴力】

    Morgana is learning computer vision, and he likes cats, too. One day he wants to find the cat moveme ...

  7. SQL---->mySQl数据库1------jdbc简单入门

    JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问. 目的:不用学习每个数据库的驱动,学 ...

  8. 分区实践 A PRIMARY KEY must include all columns in the table's partitioning function

    MySQL :: MySQL 8.0 Reference Manual :: 23 Partitioning https://dev.mysql.com/doc/refman/8.0/en/parti ...

  9. Postgresql 正则表达式(转)

    原文:http://blog.csdn.net/wugewuge/article/details/7704996 postgresql支持POSIX 风格的正则表达式,在postgresql中使用正则 ...

  10. python采用pika库使用rabbitmq总结,多篇笔记和示例(转)

    add by zhj:作者的几篇文章参考了Rabbitmq的Tutorials中的几篇文章. 原文:http://www.01happy.com/python-pika-rabbitmq-summar ...