多线程的异常处理

本文摘自:Java并发编程从入门到精通(张振华     著)

在并发编程中,run( )方法不允许thorw exception,所有的异常必须在run方法内进行处理。

在java多线程程序中,所有的线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉。这一点是通过java.lang.Runnable.run( )方法声明(因为此方法声明上没有throw exception部分)进行了约束。但是线程依然有可能抛出unchecked exception,当抛出此类异常时,线程就会终结,而对于主线程和其他线程完全不受影响,且完全感知不到某个线程抛出的异常,也就是说完全无法catch到这个异常。

因此,在thread里面,如果要处理checked exception,简单的一个try/catch块就可以了。对于这种unchecked exception,相对来说就会有点不一样。

这是就要用到Thread里面的setUncaughtExceptionHandler(UncaughtExceptionHandler),这个方法可以用来处理一些unchecked exception。setUncaughtExceptionHandler( )方法相当于一事件注册的入口。在Thread类里面的源码如下:

<span style="font-size:14px;">public void setUncaughtExceptionHandler(UncaughtExceptionHandler paramUncaughtExceptionHandler)
{
 	checkAccess();
 	this.uncaughtExceptionHandler = paramUncaughtExceptionHandler;
}
</span>

<span style="font-family:Courier New;font-size:14px;background-color: rgb(240, 240, 240);">而UncaughtExceptionHandler则是一个接口;它的声明如下:</span>
<span style="font-size:14px;">public static abstract interface UncaughtExceptionHandler
{
	public anstract void uncaughtException(Thread paramThread, Throwable paramThrowable);
}
</span>
<span style="font-size:14px;">在异常发生时,我们传入的 UncaughtExceptionHandler参数的uncaughtException方法会被调用。</span>
<span style="font-size:14px;">综合前面的讨论,我们把要实现handle unchecked exception的方法的具体步骤总结如下:</span>
<span style="font-size:14px;">(1)定义一个类实现UncaughtExceptionHandler接口。在实现的方法里包含对异常处理的逻辑和步骤。</span>
<span style="font-size:14px;">(2)定义线程执行结构和逻辑。这一步和普通线程定义一样。</span>
<span style="font-size:14px;">(3)在创建和执行该子线程的方法中,在thread.start( )语句前增加一个thread.setUncaughtExceptionHandler语句来实现处理逻辑的注册</span>
<span style="font-size:14px;">
</span>
<span style="font-size:14px;">下面按照这个步骤来创建一个示例:</span>
<span style="font-size:14px;">首先是实现UncaughtExceptionHandler接口部分
</span>
<span style="font-size:14px;">package demo.thread;

import java.lang.Thread.UncaughtExceptionHandler;

public class ExceptionHandlerThreadB implements UncaughtExceptionHandler {
		public void uncaughtException(Thread t, Throwable e) {
			System.out.printf("An exception has been captured\n");
			System.out.printf("Thread: %s\n", t.getId());
			System.out.printf("Exception: %s: %s\n", 
					e.getClass().getName(), e.getMessage());
			System.out.printf("Stack Trace: \n");
			e.printStackTrace(System.out);
			System.out.printf("Thread status: %s\n", t.getState());
		}
	}
</span>

<span style="font-size:14px;">这里我们添加的异常处理逻辑很简单,只是把线程的信息和异常信息都打印出来。</span>
<span style="font-size:14px;">然后,我们定义线程的内容,这里,我们故意让线程产生一个unchecked exception:</span>
<span style="font-size:14px;">package demo.thread;

public class ThreadB implements Runnable {
	public void run() {
		int number0 = Integer.parseInt("TTT");
	}
}
</span>

<span style="font-size:14px;">从上面的代码中我们可以看到,Integer.parseInt()里面的参数是错误的,肯定会抛出一个异常来。</span>
<span style="font-size:14px;">现在,我们再把创建线程和注册处理逻辑的部分补上来:</span>
<span style="font-size:14px;">package demo.thread;
public class ThreadMain {
	public static void main(String[] args) {
		ThreadB task = new ThreadB();
		Thread thread = new Thread(task);
		thread.setUncaughtExceptionHandler(new ExceptionHandlerThreadB());
		thread.start();
	}
}</span>

<span style="font-size:14px;">现在我们执行整个程序,会发现有如下的结果
</span>
<span style="font-size:14px;">An exception has been captured
Thread: 10
Exception: java.lang.NumberFormatException: For input string: "TTT"
Stack Trace: 
java.lang.NumberFormatException: For input string: "TTT"
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at unit2.ThreadB1.run(ThreadB1.java:5)
	at java.lang.Thread.run(Unknown Source)
Thread status: RUNNABLE
</span>


这部分的输出正好就是我们前面实现UncaughtExceptionHandler接口的定义。

因此,对于unchecked exception,我们也可以采用类似事件注册的机制做一定程度的处理,当然也可以不做处理放任自由,读者可以试试效果什么怎么样的,这里不再实验。

总之,Java thread里面关于异常的部分比较奇特。你不能直接在一个线程里面去抛出异常。一般在线程里碰到checked exception,推荐的做法是采用try/catch块来处理。而对于unchecked exception,比较合理的方式是注册一个实现UncaughtExceptionHandler接口的对象实例来处理。

<span style="font-size:14px;">
</span>



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值