• Java线程-异常处理


      在Java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉。这一点是通过java.lang.Runnable.run()方法声明(因为此方法声明上没有throw exception部分)进行了约束。但是线程依然有可能抛出unchecked exception,当此类异常抛出时,线程就会终结,而对于主线程和其他线程完全不受影响,且完全感知不到某个线程抛出的异常(也是说完全无法catch到这个异常)。JVM的这种设计源自于这样一种理念:“线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部。”基于这样的设计理念,在Java中,线程方法的异常(无论是checked还是unchecked exception),都应该在线程代码边界之内(run方法内)进行try catch并处理掉。下面看两个例子:

    例子一:IOException是一个chedked exception,在这里看到了报错,编译不通过。

    例子二:想捕线程的非检查异常,发现也不能捕获

    public class MyThread2 implements Runnable {
        @Override
        public void run() {
            int i = 1/0; //此处会报非检查异常
        }
    
        public static void main(String[] args) {
            try {
                Thread t = new Thread(new MyThread2());
                t.start();
            } catch (Exception e) {
                //想在外面捕获异常,但是获取不到
                System.out.println("分母不能是零啊");
            }
        }
    }

    运行结果:

    Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
    at org.burning.sport.javase.thread.MyThread2.run(MyThread2.java:11)
    at java.lang.Thread.run(Thread.java:745)

    从运行结果看到,catch代码块中并没有打印输出

    那如果我们需要捕获线程跑出的异常并做处理的话改怎么办呢?

      方法一:在run()方法中用try catch来捕获这个异常并做处理

    public class MyThread implements Runnable {
        @Override
        public void run() {
            try {
                int i = 1/0;
            } catch (Exception e) {
                System.out.println("这里有问题,可以通知给其他人:" + e); //这里可以做捕获异常后的其他操作,比如发消息给第三方
            }
        }
    
        public static void main(String[] args) {
            Thread t = new Thread(new MyThread());
            t.start();
        }
    }

    结果:

    这里有问题,可以通知给其他人:java.lang.ArithmeticException: / by zero

      方法二:我们想在线程边界之外捕获这个异常的(run()方法之外)的话,那我们就要用到Java给我们提供的UncaughtExceptionHandler处理方法

    步骤一:定义一个自己的异常处理器

    package org.burning.sport.javase.thread.exception;
    
    public class MyUncatchException implements Thread.UncaughtExceptionHandler {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("当前线程的名字:" + t.getName());
            System.out.println("发生了什么问题:" + e );
        }
    }

    步骤二:在线程启动前设置自定义的异常处理器

    package org.burning.sport.javase.thread.exception;
    
    public class ExceptionThread implements Runnable {
        @Override
        public void run() {
            System.out.println("将要悲剧了");
            int i = 1/0;
    
        }
    
        public static void main(String[] args) {
            Thread t = new Thread(new ExceptionThread());
            //这里设置自定义的异常处理器
            t.setUncaughtExceptionHandler(new MyUncatchException());
            t.start();
        }
    }

    结果:

    将要悲剧了
    当前线程的名字:Thread-0
    发生了什么问题:java.lang.ArithmeticException: / by zero

    小结:

      如果在run方法中没有发生异常,那么就不会去运行MyUncatchException

    如果用线程池来启动线程的话还可以用ThreadFactory来设置异常处理器

    步骤一:同上

    步骤二:自定义一个ThreadFactory

    package org.burning.sport.javase.thread.exception;
    
    import java.util.concurrent.ThreadFactory;
    
    public class HandlerThreadFactory implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            System.out.println("线程名称:" + t);
            t.setUncaughtExceptionHandler(new MyUncatchException()); //设置异常处理器
            System.out.println("好恐怖:" + t.getUncaughtExceptionHandler());
            return t;
        }
    }

    步骤三:通过线程池启动线程

    package org.burning.sport.javase.thread.exception;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ExceptionThread implements Runnable {
        @Override
        public void run() {
            System.out.println("将要悲剧了");
            int i = 1/0;
        }
    
        public static void main(String[] args) {
            ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
            exec.execute(new ExceptionThread());
        }
    }

    结果:

    线程名称:Thread[Thread-0,5,main]
    好恐怖:org.burning.sport.javase.thread.exception.MyUncatchException@4b9af9a9
    将要悲剧了
    线程名称:Thread[Thread-1,5,main]
    好恐怖:org.burning.sport.javase.thread.exception.MyUncatchException@34d6cbd5
    当前线程的名字:Thread-0
    发生了什么问题:java.lang.ArithmeticException: / by zero

    参考:

    [1] 博客,https://www.cnblogs.com/brolanda/p/4725138.html

  • 相关阅读:
    Multi-Channel MAC for Ad Hoc Networks: Handling Multi-Channel Hidden Terminals Using A Single Transceiver
    Cognitive Radio Emergency Networks – Requirements and Design
    OS-MAC: An Efficient MAC Protocol for Spectrum-Agile Wireless Networks
    OSA-MAC: A MAC Protocol for Opportunistic Spectrum Access in Cognitive Radio Networks
    HC-MAC: A Hardware-Constrained Cognitive MAC for Efficient Spectrum Management
    用HTWCore智能"记笔记"
    基于.NET Core winform的录音、字幕软件HTWCore的技术总结
    用人工智能工具解决工作中遇到的录音整理、速录行业的问题
    一段讯飞、百度等语音识别API无法识别的语音最终解决办法
    c#项目调用Python模块的方法
  • 原文地址:https://www.cnblogs.com/happyflyingpig/p/7992504.html
Copyright © 2020-2023  润新知