• 技术文章 >Java >java教程

    多线程捕获并处理RuntimeException的代码实例

    Y2JY2J2017-04-25 09:10:49原创1190

    在多线程的机制下,我们不能跨越线程在主线程中捕获其他线程的异常。

    对于非运行时异常,在线程很多很复杂的时候,为每个线程都写一份异常处理程序也很难过。对于运行时异常,如果我们不能采取一些有用的措施,那么异常会被抛出到控制台上。

    比如下面的例子:

    package AllThread;/**
     * 
     * @author QuinnNorris
     * 
     *         捕获异常
     */public class ExceptionThread {
    
        /**
         * @param args
         */
        public static void main(String[] args) {        // TODO Auto-generated method stub
    
            Thread th = new Thread(new Runnable() {            @Override
                public void run() {                // TODO Auto-generated method stub
                    throw new RuntimeException();
                }
            });
            th.start();
        }
    
    }

    这是一段简单的代码,它会抛出一个运行时异常:

    Exception in thread “Thread-0” java.lang.RuntimeException  
    
      at AllThread.ExceptionThread$1.run(ExceptionThread.java:15)  
    
      at java.lang.Thread.run(Thread.java:745)

    我们可以看出, 由于没有去设计捕获异常,它被直接输出到控制台上。对于这种情况,为main函数加上try-catch语句是没有用的。

    为了增加对异常处理的手段,在JAVA SE5中引入了使用Executor的一种解决方法。

    package AllThread;import java.lang.Thread.UncaughtExceptionHandler;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;/**
     * 
     * @author QuinnNorris
     * 
     *         使用UncaughtExceptionHandler捕获异常
     */public class UEHThread {
    
        /**
         * @param args
         */
        public static void main(String[] args) {        // TODO Auto-generated method stub
            ExecutorService es = Executors.newCachedThreadPool(new ThreadFactory() {            @Override
                public Thread newThread(Runnable r) {                // TODO Auto-generated method stub
                    Thread th = new Thread(r);
                    th.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {                    @Override
                        public void uncaughtException(Thread t, Throwable e) {                        // TODO Auto-generated method stub
                            System.out.println("catch it " + e);
                        }
    
                    });                return th;
                }
    
            });
            es.execute(new Runnable() {            @Override
                public void run() {                // TODO Auto-generated method stub
                    throw new RuntimeException();
                }
    
            });
    
        }
    
    }

    因为我比较懒全部用内部类来表示,所以这段程序可能略有些难懂。

    1. 首先我们创建了一个线程池,然后为这个创建线程池的静态方法赋予一个参数。这个参数是一个ThreadFactory类,这个类是用来描述在线程池中的线程具有的共性的。

    2. ThreadFactory有一个方法需要我们覆盖就是newThread方法,这个方法的参数是我们要处理的Runnable任务,也就是我们要加入到线程池中的Runnable任务。

    3. 我们在这个方法中用一个th对象包含r对象,然后设置th对象的UncaughtExceptionHandler属性。

    4. 这个setUncaughtExceptionHandler方法的参数是一个UncaughtExceptionHandler对象,这里我们第二次用内部类。

    5. UncaughtExceptionHandler类的唯一一个方法是uncaughtException。这个方法用来表示对线程未检查异常的处理方式,我们让他在控制台输出一句话。到这里我们对线程池的部署就完成了。

    6. 然后我们在这个线程池中添加一个Runnable任务,这个任务会抛出一个未检查异常。

    现在我们运行程序,控制台输出:

    catch it java.lang.RuntimeException

    到此,对于线程run方法中的未检查异常的处理就结束了。需要注意的是,我们向线程池中添加线程的方法要调用execute方法而不要使用submit方法,submit方法会把异常吞掉。从而控制台将会什么都不输出。

    在多线程的机制下,我们不能跨越线程在主线程中捕获其他线程的异常。

    对于非运行时异常,在线程很多很复杂的时候,为每个线程都写一份异常处理程序也很难过。对于运行时异常,如果我们不能采取一些有用的措施,那么异常会被抛出到控制台上。

    比如下面的例子:

    package AllThread;/**
     * 
     * @author QuinnNorris
     * 
     *         捕获异常
     */public class ExceptionThread {
        /**
         * @param args
         */
        public static void main(String[] args) {        // TODO Auto-generated method stub
    
            Thread th = new Thread(new Runnable() {            @Override
                public void run() {                // TODO Auto-generated method stub
                    throw new RuntimeException();
                }
            });
            th.start();
        }
    }

    这是一段简单的代码,它会抛出一个运行时异常:

    Exception in thread “Thread-0” java.lang.RuntimeException  
      at AllThread.ExceptionThread$1.run(ExceptionThread.java:15)  
      at java.lang.Thread.run(Thread.java:745)

    我们可以看出, 由于没有去设计捕获异常,它被直接输出到控制台上。对于这种情况,为main函数加上try-catch语句是没有用的。

    为了增加对异常处理的手段,在JAVA SE5中引入了使用Executor的一种解决方法。

    package AllThread;import java.lang.Thread.UncaughtExceptionHandler;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;/**
     * 
     * @author QuinnNorris
     * 
     *         使用UncaughtExceptionHandler捕获异常
     */public class UEHThread {
    
        /**
         * @param args
         */
        public static void main(String[] args) {        // TODO Auto-generated method stub
            ExecutorService es = Executors.newCachedThreadPool(new ThreadFactory() {            @Override
                public Thread newThread(Runnable r) {                // TODO Auto-generated method stub
                    Thread th = new Thread(r);
                    th.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {                    @Override
                        public void uncaughtException(Thread t, Throwable e) {                        // TODO Auto-generated method stub
                            System.out.println("catch it " + e);
                        }
    
                    });                return th;
                }
    
            });
            es.execute(new Runnable() {            @Override
                public void run() {                // TODO Auto-generated method stub
                    throw new RuntimeException();
                }
    
            });
    
        }
    }

    因为我比较懒全部用内部类来表示,所以这段程序可能略有些难懂。

    1. 首先我们创建了一个线程池,然后为这个创建线程池的静态方法赋予一个参数。这个参数是一个ThreadFactory类,这个类是用来描述在线程池中的线程具有的共性的。

    2. ThreadFactory有一个方法需要我们覆盖就是newThread方法,这个方法的参数是我们要处理的Runnable任务,也就是我们要加入到线程池中的Runnable任务。

    3. 我们在这个方法中用一个th对象包含r对象,然后设置th对象的UncaughtExceptionHandler属性。

    4. 这个setUncaughtExceptionHandler方法的参数是一个UncaughtExceptionHandler对象,这里我们第二次用内部类。

    5. UncaughtExceptionHandler类的唯一一个方法是uncaughtException。这个方法用来表示对线程未检查异常的处理方式,我们让他在控制台输出一句话。到这里我们对线程池的部署就完成了。

    6. 然后我们在这个线程池中添加一个Runnable任务,这个任务会抛出一个未检查异常。

    现在我们运行程序,控制台输出:

    catch it java.lang.RuntimeException

    到此,对于线程run方法中的未检查异常的处理就结束了。需要注意的是,我们向线程池中添加线程的方法要调用execute方法而不要使用submit方法,submit方法会把异常吞掉。从而控制台将会什么都不输出。

    以上就是多线程捕获并处理RuntimeException的代码实例的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:关于java覆盖equals更深层的方法概述 下一篇:java并发--全部线程机制实例详解
    千万级数据并发解决方案

    相关文章推荐

    • 带你搞懂Java结构化数据处理开源库SPL• 一文搞懂Java接口• 一起来理解Java中的泛型• 整理分享Java语言表达式的五个谜题• 详细整理java枚举的使用总结
    1/1

    PHP中文网