深入浅出 Java Concurrency (36): 线程池 part 9 并发操作异常体系[转]
并发包引入的工具类很多方法都会抛出一定的异常,这些异常描述了任务在线程池中执行时发生的例外情况,而通常这些例外需要应用程序进行捕捉和处理。
例如在Future接口中有如下一个API:
在前面的章节中描述了Future类的具体实现原理。这里不再讨论,但是比较好奇的抛出的三个异常。
这里有一篇文章(Java 理论与实践: 处理 InterruptedException)描述了InterruptedException的来源和处理方式。简单的说就是线程在执行的过程中被自己或者别人中断了。这时候为了响应中断就需要处理当前的异常。
对于java.lang.Thread而言,InterruptedException也是一个很诡异的问题。
中断一个线程Thread.interrupt()时会触发下面一种情况:
如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。
检测一个线程的中断状态描述是这样的Thread.interrupted():
测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
也就是说如果检测到一个线程已经被中断了,那么线程的使用方(挂起、等待或者正在执行)都将应该得到一个中断异常,同时将会清除异常中断状态。
if (!tryAcquireSharedNanos(0, nanosTimeout))
throw new TimeoutException();
if (getState() == CANCELLED)
throw new CancellationException();
if (exception != null)
throw new ExecutionException(exception);
return result;
}
上面获取任务结果的方法实现中,将在获取锁的过程中得到一个中断异常。代码java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(int, long)描述了这种情况:
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
这里在获取锁的时候检测线程中断情况,如果被中断则清除中断位,同时抛出一个中断异常。为什么如此做?因为我们的线程在线程池中是被重复执行的,所以一旦线程被中断后并不会退出线程,而是设置中断位,等候任务队列自己处理线程,从而达到线程被重复利用的目的。有兴趣的可以参考代码java.util.concurrent.ThreadPoolExecutor.Worker.runTask(Runnable)。这里在关闭线程池时就会导致中断所有线程。
除了InterruptedException 异常我们还发现了一个全新的异常java.util.concurrent.TimeoutException,此异常是用来描述任务执行时间超过了期望等待时间,也许是一直没有获取到锁,也许是还没有执行完成。
在innerGet代码片段中我们看到,如果线程在指定的时间无法获取到锁,那么就会得到一个超时异常。这个很好理解,比如如果执行一个非常耗时的网络任务,我们不希望任务一直等待从而占用大量的资源,可能在一定时间后就会希望取消此操作。此时超时异常很好的描述了这种需求。
与此同时,如果取消了一个任务,那么再次从任务中获取执行结果,那么将会得到一个任务被取消的异常java.util.concurrent.CancellationException。
除了上述异常外,还将得到一个java.util.concurrent.ExecutionException异常,
这是因为我们的提交的任务java.util.concurrent.Callable在call()方法中允许抛出任何异常,另外常规的线程执行也可能抛出一个RuntimeException,所以这里简单包装了下所有异常,当作执行过程中发生的异常ExecutionException抛出。
以上就是整个异常体系,所有并发操作的异常都可以归结于上述几类。
很多情况下处理时间长度都是用java.util.concurrent.TimeUnit,这是一个枚举类型,用来描述时间长度。其中内置了一些长度的单位。其中包括纳秒、微秒、毫秒、秒、分、时、天。例如超时操作5秒,可以使用
Future.get(5,TimeUnit.SECONDS) 或者 Future.get(5000L,TimeUnit.MILLISECONDS)
当然一种单位的时间转换成另一种单位的时间也是非常方便的。另外还有线程的sleep/join以及对象的wait操作的便捷操作。
深入浅出 Java Concurrency (36): 线程池 part 9 并发操作异常体系[转]的更多相关文章
- 深入浅出 Java Concurrency (28): 线程池 part 1 简介[转]
从这一节开始正式进入线程池的部分.其实整个体系已经拖了很长的时间,因此后面的章节会加快速度,甚至只是一个半成品或者简单化,以后有时间的慢慢补充.完善. 其实线程池是并发包里面很重要的一部分,在实际情况 ...
- 深入浅出 Java Concurrency (35): 线程池 part 8 线程池的实现及原理 (3)[转]
线程池任务执行结果 这一节来探讨下线程池中任务执行的结果以及如何阻塞线程.取消任务等等. 1 package info.imxylz.study.concurrency.future;2 3 publ ...
- 深入浅出 Java Concurrency (34): 线程池 part 7 线程池的实现及原理 (2)[转]
线程池任务执行流程 我们从一个API开始接触Executor是如何处理任务队列的. java.util.concurrent.Executor.execute(Runnable) Executes t ...
- 深入浅出 Java Concurrency (33): 线程池 part 6 线程池的实现及原理 (1)[转]
线程池数据结构与线程构造方法 由于已经看到了ThreadPoolExecutor的源码,因此很容易就看到了ThreadPoolExecutor线程池的数据结构.图1描述了这种数据结构. 图1 Thre ...
- 深入浅出 Java Concurrency (30): 线程池 part 3 Executor 生命周期[转]
我们知道线程是有多种执行状态的,同样管理线程的线程池也有多种状态.JVM会在所有线程(非后台daemon线程)全部终止后才退出,为了节省资源和有效释放资源关闭一个线程池就显得很重要.有时候无法正确的关 ...
- 深入浅出 Java Concurrency (29): 线程池 part 2 Executor 以及Executors[转]
Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具.真正的线程池接口是ExecutorService. 下面这张图完整描述了线程 ...
- [转] 多线程 《深入浅出 Java Concurrency》目录
http://ifeve.com/java-concurrency-thread-directory/ synchronized使用的内置锁和ReentrantLock这种显式锁在java6以后性能没 ...
- 《深入浅出 Java Concurrency》目录
最近在学习J.U.C,看到一个大神 关于这个系列写的非常精辟,由于想做笔记,故系列转载并记录之. 原文:http://www.blogjava.net/xylz/archive/2010/07/08/ ...
- 深入浅出 Java Concurrency - 目录 [转]
这是一份完整的Java 并发整理笔记,记录了我最近几年学习Java并发的一些心得和体会. J.U.C 整体认识 原子操作 part 1 从AtomicInteger开始 原子操作 part 2 数组. ...
随机推荐
- 《Java语言程序设计》编程练习6.18(检测密码)
6.18 (检测密码)一些网站对于密码具有一些规则.编写一个方法,检测字符串是否是一个有效密码. 假定密码规则如下: • 密码必须至少8位字符. • 密码仅能包含字母和数字. ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 G. Colorful String 回文树
签到提: 题意:求出每一个回文串的贡献 (贡献的计算就是回文串不同字符的个数) 题解: 用回文树直接暴力即可 回文树开一个数组cost[ ][26] 和val[ ] 数组: val[i]表示回文树上节 ...
- 【python】collections的使用
老师布置了一个课后作业. 统计文本中字母出现的次数并找到最大的那一个 首先是读取文本吧.和c里的也差不多,打开,关闭,读取. path = f = f.close() 然后就用到了这个黑科技.coll ...
- 知识图谱+Recorder︱中文知识图谱API与工具、科研机构与算法框架
目录 分为两个部分,笔者看到的知识图谱在商业领域的应用,外加看到的一些算法框架与研究机构. 文章目录 @ 一.知识图谱商业应用 01 唯品金融大数据 02 PlantData知识图谱数据智能平台 03 ...
- springboot整合thymeleaf手动渲染
Thymeleaf手动渲染 为提高页面访问速度,可缓存html页面,客户端请求从缓存获取,获取不到再手动渲染 在spring4下 @Autowired ThymeleafViewResolver th ...
- Shell 学习(三)
目录 Shell 学习(三) 流程控制 1 if判断 2 case 语句 3 for循环 4 while 循环 2 read 读取控制台输入 2.1 基本语法 2.2 应用实例 3 函数 3.1 系统 ...
- arm-linux-objdump 的使用
1. 查看静态库或.o 文件的组成文件 [arm@localhost gcc]$ armlinuxobjdump a libhello.a 2. 查看静态库或.o 文件的络组成部分的头部分 [a ...
- C#利用资源文件设置软件自适应多语言
在项目更目录下添加两个资源文件,以适应中英文两种版本,如Resource.zh_CN.resx和 Resource.en-US.resx ,两个资源文件的ID都一样,值分别配置相应的中英文 ...
- JS去除字符串拼接末尾的符号(逗号)
前言:在JS中,有时需要进行字符串的拼接,而拼接的字符串以某种符号分隔,在拼接好的字符串末尾会多出一个分隔符,这时我们可以采取以下几种方法来去除末尾的分隔符. 方法一:使用substring() 和 ...
- 双十一HostGator独立服务器方案
一年一度的“双十一”购物狂欢节到来,各大电商平台线上消费的各种“吸金”开启了“双十一”模式,一年一度的“双十一”网购狂欢又开始以“巨大的价格优势”来勾起消费者的购买欲望. 此次双十一期间,HostGa ...