JAVA UncaughtExceptionHandler 处理

原创 2016年08月28日 22:21:49

Thread的run方法是不抛出任何检查型异常(checked exception)的,但是它自身却可能因为一个异常而被终止,导致这个线程的终结。最麻烦的是,在线程中抛出的异常即使使用try…catch也无法截获,因此可能导致一些问题出现,比如异常的时候无法回收一些系统资源,或者没有关闭当前的连接等等。
(PS:Callalble是可抛出异常)

如果需要捕获系统的未捕获异常(如系统抛出了未知错误,这种异常没有捕获,这将导致系统莫名奇妙的关闭,使得用户体验差),可以通过Thread.setUncaughtExceptionHandler(UncaughtExceptionHandler)来处理这种异常。

例子:

public class ExceptionHandler implements UncaughtExceptionHandler{

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("handle run in thread:"+Thread.currentThread().getName());

        System.out.println("thread:"+t.getName()+" throwing exception");
        e.printStackTrace();    
    }

}

public class Test implements Runnable{
    public static void main(String args[]) throws InterruptedException, FileNotFoundException, IOException, ClassNotFoundException 
    {

        Thread t=new Thread(new Test());
        t.setUncaughtExceptionHandler(new ExceptionHandler());
        t.start();
    }

输出:

run func
exception thread running:Thread-0
handle run in thread:Thread-0
thread:Thread-0 throwing exception
java.lang.RuntimeException
    at Test.fun(Test.java:43)
    at Test.run(Test.java:37)
    at java.lang.Thread.run(Unknown Source)

另外,这个例子同时也说明了异常处理函数UncaughtExceptionHandle是运行在抛出异常的线程中的。

如果是使用了线程池,那应该如何处理呢?
我们知道线程池中我们只能提交Runable,Callable对象,而不是Thread对象,代码类似与:

        ExecutorService pool=Executors.newCachedThreadPool();
        for(int i=0;i<10;i++)
        {
            Test task=new Test();
            pool.execute(task);
        }

为了能够也能设置UncaughtExceptionHandler,我们能够通过线程池的ThreadFactory,使得线程池中的线程特殊化。
代码如下:

import java.lang.Thread.UncaughtExceptionHandler;

public class ExceptionHandler implements UncaughtExceptionHandler{

    public static ExceptionHandler instance=new ExceptionHandler();

    public static ExceptionHandler getInstance()
    {
        return instance;
    }

    @Override
    synchronized public void uncaughtException(Thread t, Throwable e) {

        System.out.println("handle run in thread:"+Thread.currentThread().getName());       
        System.out.println("thread:"+t.getName()+" throwing exception");
        StackTraceElement ele[]  =e.getStackTrace();
        for(StackTraceElement s:ele)
        {
            System.out.println("\t"+s.toString());
        }

    }

}

上面的handle方法同步是为了输出信息更好辨认,并无其他特殊需求。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

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


class SpecialThreadFactory implements ThreadFactory{

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

}


public class Test implements Runnable{
    public static void main(String args[]) throws InterruptedException, FileNotFoundException, IOException, ClassNotFoundException 
    {
        ExecutorService pool=Executors.newCachedThreadPool(new SpecialThreadFactory());
        for(int i=0;i<10;i++)
        {
            Test task=new Test();
            pool.execute(task);
        }

        pool.shutdown();
    }

    @Override
    public void run() {
        fun();  
    }
    public static void fun()
    {
        throw new RuntimeException();
    }

}

结果

handle run in thread:Thread-1
thread:Thread-1 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-3
thread:Thread-3 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-5
thread:Thread-5 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-7
thread:Thread-7 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-9
thread:Thread-9 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-0
thread:Thread-0 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-2
thread:Thread-2 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-4
thread:Thread-4 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-6
thread:Thread-6 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-8
thread:Thread-8 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)

总结
1.UncaughtExceptionHandler用来处理线程未捕获异常,在发生异常的线程中运行处理代。
2.线程池中的线程通过ThreadFactory来进行UncaughtExeceptionHandle的注册。

3.突然想到一个问题:如果抛出异常的线程遇到不可恢复的异常,则还能运行handle相关代码么?

版权声明:转载 请标注 出处

相关文章推荐

Android使用UncaughtExceptionHandler捕获全局异常

UncaughtExceptionHandler可以用来捕获程序异常,比如NullPointerException空指针异常抛出时,用户没有try catch捕获,那么,Android系统会弹出对话框...

JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止

当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境中,线程抛出的异常是不能用try....catch捕获的,这样就有可能导致一些问题的出现,比如异...

Android Thread.UncaughtExceptionHandler捕获

在Java 的异常处理机制中: 如果抛出的是Exception异常的话,必须有try..catch..进行处理,属于checked exception。 如果抛出的是RuntimeExceptio...
  • wangbole
  • wangbole
  • 2012年11月08日 12:03
  • 17072

【Android开发】UncaughtExceptionHandler接口详解

Android开发:UncaughtExceptionHandler接口详解

Android使用UncaughtExceptionHandler捕获全局异常

1. 前言Android应用出现crash时,会出现“程序异常退出”的提示,随后应用关闭,用户体验非常不好。一般为了捕获应用运行时异常后做出适当处理,给出合理提示时,我们开发中可以继承Uncaught...

手写CrashHandler实现UncaughtExceptionHandler拦截android异常

手写CrashHandler实现UncaughtExceptionHandler拦截android异常作者:码字员小D有点复杂,虽然知道原理,但是并不好从哪开始写了。。。。。。首先这是个需要在整个ap...

Java异常处理之处理未捕获的异常及UncaughtExceptionHandler的使用

UncaughtExceptionHandler是为了捕获没有被捕获的异常,包括运行时异常,执行错误(内存溢出等),子线程抛出的异常等 下面的代码在子线程中模拟一个异常,并在主线程中试图捕获异常...

带资源的try语句

jdk 1.7之后出现的一个新的语句,主要用于关闭资源。        在原来关闭资源的时候,用 try-catch-finally 时如果try中的代码跑出了一个非 IOException,在执行f...

java中volatile关键字

synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用synch...

java线程处理异常Thread.UncaughtExceptionHandler

java线程处理异常Thread.UncaughtExceptionHandler
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JAVA UncaughtExceptionHandler 处理
举报原因:
原因补充:

(最多只允许输入30个字)