并发包引入的工具类不少方法都会抛出必定的异常,这些异常描述了任务在线程池中执行时发生的例外状况,而一般这些例外须要应用程序进行捕捉和处理。html
例如在Future接口中有以下一个API:java
在前面的章节中描述了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。ui
检测一个线程的中断状态描述是这样的Thread.interrupted():.net
测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,若是连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态以后,且第二次调用检验完中断状态前,当前线程再次中断的状况除外)。 线程
也就是说若是检测到一个线程已经被中断了,那么线程的使用方(挂起、等待或者正在执行)都将应该获得一个中断异常,同时将会清除异常中断状态。htm
上面获取任务结果的方法实现中,将在获取锁的过程当中获得一个中断异常。代码java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(int, long)描述了这种状况:
这里在获取锁的时候检测线程中断状况,若是被中断则清除中断位,同时抛出一个中断异常。为何如此作?由于咱们的线程在线程池中是被重复执行的,因此一旦线程被中断后并不会退出线程,而是设置中断位,等候任务队列本身处理线程,从而达到线程被重复利用的目的。有兴趣的能够参考代码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操做的便捷操做。