Java并发之线程异常捕获

由于线程的本质特性,使得你不能捕获从线程中逃逸的异常,如:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class App {

	public static void main(String[] args) throws InterruptedException {
		try {
			ExecutorService exec = Executors.newCachedThreadPool();
			exec.execute(new Task());
			exec.shutdown();
		} catch (Exception e) {
			System.out.println("异常:"+e.getMessage());
		}
	}
}

/**
 * 定义任务
 * 
 * @author Administrator
 */
class Task implements Runnable {

	@Override
	public void run() {		
		throw new RuntimeException("运行时错误");
	}
}

输出:

Exception in thread "pool-1-thread-1" java.lang.RuntimeException: 运行时错误
at Task.run(App.java:27)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

可以看到一旦异常逃逸出run方法,将直接传播到顶层,且捕获不了。当然你可以在run方法里处理这些异常,但如果不想再run里处理呢?

为了解决这个问题,我们需要修改Executors产生线程的方式,Thread.setUncaughtExceptionHandler是Java5的新接口,它允许你在每个Thread对象上附着一个异常处理器。Thread.setUncaughtExceptionHandler.uncaughtException()会在线程因未捕获的异常而临近死亡时被调用。这里仍然需要用到线程工厂ThreadFactory:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class App {

	public static void main(String[] args) throws InterruptedException {
		ExecutorService exec = Executors.newCachedThreadPool(new MyThreadFactory());
		exec.execute(new Task());
		exec.shutdown();
	}
}

/**
 * 定义任务
 * 
 * @author Administrator
 */
class Task implements Runnable {

	@Override
	public void run() {		
		throw new RuntimeException("运行时错误");
	}
}

/**
 * 线程工厂
 * @author Administrator
 *
 */
class MyThreadFactory implements ThreadFactory{

	@Override
	public Thread newThread(Runnable r) {
		Thread t=new Thread(r);
		t.setUncaughtExceptionHandler(new MysetUncaughtExceptionHandler());
		return t;
	}
}

/**
 * 异常处理器
 * @author Administrator
 *
 */
class MysetUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		System.out.println("异常:"+e.getMessage());
	}
}

输出:

异常:运行时错误

其实在实际应用中根据定制,ThreadFactory是经常用到的。

出处:http://www.zhaiqianfeng.com    
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/zhaiqianfeng/p/4620135.html