Java Concurrent Programming (3)
3 线程异常
线程在执行其run方法时,很有可能抛出异常。而run方法签名中,并未声明会抛出任何检查型异常。但在实际程序中,run方法中极其可能抛出一个异常,从而导致此线程被终止。更糟糕的是,如果线程因为异常终止,我们无法在主线程中使用try...catch...进行异常的捕获,从而可能导致一些问题的发生,例如无法释放某些资源等。主线程之所以不处理子线程抛出的RuntimeException,是因为线程是异步的,子线程没结束,主线程可能已经结束了。Thread类中的setUncaughtExceptionHandler就是处理线程中那些未捕获的异常,更明确的说,它处理那些未捕获的运行时异常。以下是一个例子,:
程序的输出结果:
线程内部的处理机制是这样子的:当一个线程突然间被一个无法捕获的异常终止时,首先这个线程本身会处理这个异常,由jvm调用dispatchUncaughtException方法,查看线程是否设置了异常处理方法,如果没有为此线程设置异常处理方法,此时线程会查看此线程所在线程组是否设置了线程异常处理方法,将异常处理交给线程组,然后ThreadGroup的uncaughtException方法会处理这个异常(也由jvm调用),在这个方法里,ThreadGroup会首先判断这个线程组是否还有父线程组,如果有父线程组,则继续交由父线程组处理这个异常,如果不存在父线程组,其会调用这个线程的默认异常处理方法,如果这个线程有默认的异常处理策略,则用这个默认的异常处理策略进行异常的处理,否则的话,会判断这个异常是否属于ThreadDeath类型(extends Error),如果这个异常属于ThreadDeath类型,则放弃处理,否则打印这个异常信息。
同样,我们可以设置线程的默认异常处理策略,通过setDefaultUncaughtExceptionHandler即可,我们也可以通过调用getDefaultUncaughtExceptionHandler和getUncaughtExceptionHandler得到线程默认的异常处理程序信息和线程异常处理程序信息
3.1 InterruptedException异常
Thread.sleep()、 Thread.join() 或 Object.wait()都可以抛出InterruptedException,它是一个检查异常(checked exception)。当一个线程在wait set中等待或者调用了sleep方法,而另一个线程调用了interrupt方法中断当前线程时,就会抛出InterruptedException。
当一个方法抛出InterruptedException,表示这个方法是一个阻塞方法。
3.2 阻塞方法
阻塞的方法,不同于一般的普通方法。一般方法的完成只取决于它所要做的事情,以及是否有足够多可用的计算资源。而阻塞的方法还要取决于外部的一些事件,例如I/O完成,等待另一个线程释放对象锁等。一般方法在他们的工作做完后即可结束,而阻塞方法却不一定,其结束很难预测,因为他们还受外部因素的影响。
阻塞方法可能因为等不到外部的事件而无法结束,那么让阻塞方法可取消就非常有用。可取消是指能从外部使之在正常结束工作前终止的操作。由Thread 提供并受 Thread.sleep()和Object.wait()支持的中断机制就是一种取消机制;它允许一个线程请求另一个线程停止它正在做的事情。当一个方法抛出 InterruptedException时,它是在告诉您,如果执行该方法的线程被中断,它将尝试停止它正在做的事情而提前返回,并通过抛出InterruptedException表明它提前返回。
3.3 处理InterruptedException异常
如果一个方法抛出InterruptedException,表示这个方法为阻塞的方法,那么调用这个阻塞方法的方法也是一个阻塞方法。所以,我们必须有策略来处理InterruptedException异常。
3.3.1 将InterruptedException异常传递给调用者
good,这块一直没怎么闹明白,顺便问下这个是自己写的还是翻译的那本java 并发编程?