Java多线程异常处理

Java多线程异常处理

UncaughtExceptionHandler处理未捕获的异常

多线程的异常的有别于主线程的异常,多线程的异常异常一般只能在各自的run()方法中进行try-catch,外层的主线程使用try-catch,一般情况下对线程异常无法成功捕获。这是因为在线程Thread类中有一个接口 UncaughtExceptionHandler,它包含了一个uncaughtRxception()方法。当线程运行时候出现了异常而终止的时候,但该异常又没有try-catch的时候就会触发此方法,由于Java的Thread类默认使用uncaughtException()进行空处理,而 Java 虚拟机又会忽略该方法之后的异常抛出。所以就导致在外线程无法对内线程进行try-catch,捕获到内线程的异常。源码如下

    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        /**
         * Method invoked when the given thread terminates due to the
         * given uncaught exception.
         * <p>Any exception thrown by this method will be ignored by the
         * Java Virtual Machine.
         * @param t the thread
         * @param e the exception
         */
        void uncaughtException(Thread t, Throwable e);
    }

使用UncaughtExceptionHandler处理未捕获的异常

  1. 编写自定义的异常处理类,实现Thread.UncaughtExceptionHandler接口重写其 uncaughtException方法
  2. 编写一个类实现ThreadFactroy接口类,重写其newThread方法,通过setUncaughtExceptionHandler将自定义异常处理类设置为Thread的默认异常处理类。
// 1.编写自定义异常处理类
class SuccessCatchThreadExceptionHandler implements Thread.UncaughtExceptionHandler{
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t.getName()+"抛出了异常:"+e.toString());
    }
}
// 2.通过线程处理异常工厂类,将自定义线程处理异常处理类放入并运行
class SuccessCatchThreadExceptionFactory implements ThreadFactory{

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

运行结果展示

public class MyTryThread {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool(
                new SuccessCatchThreadExceptionFactory()
        );
        executorService.execute(new DividerByZeroRunnable());
    }
}

class DividerByZeroRunnable implements Runnable{

    @Override
    public void run() {
        int dividend = 30 ;
        int divisor = 3;
        int step =1;
        while(divisor >= 0){
            System.out.println(dividend+"与"+divisor+"相除结果为:"+dividend/divisor);
            divisor--;
        }
        System.out.println("结束运算");
    }
}
//结果
30与3相除结果为:10
30与2相除结果为:15
30与1相除结果为:30
Thread-0抛出了异常:java.lang.ArithmeticException: / by zero

Process finished with exit code 0

线程内run()进行异常处理

public class TryThread {
    public static void main(String[] args) {
        Thread thread01 = new Thread(new TrowsExceptionRunnable());
        try{
            thread01.start();
        }catch (Exception e){
            System.out.println("成功在main()方法捕获到异常!");
        }
    }
}
class TrowsExceptionRunnable implements Runnable {

    @Override
    public void run() {
        int dividend = 30 ;
        int divisor = 3;
        int step =1;
        while(divisor >= 0){
            try{
                System.out.println(dividend+"与"+divisor+"相除结果为:"+dividend/divisor);
            }catch(Exception e){
                System.out.println("成功在run()方法中捕获到线程异常!");
            }
            divisor--;
        }
        System.out.println("结束运算");
    }
}
// 从结果可以发现 在main线程中没有捕获到内部线程的异常

30与3相除结果为:10
30与2相除结果为:15
30与1相除结果为:30
成功在run()方法中捕获到线程异常!
结束运算

Process finished with exit code 0


Future的get()方法获取异常

public class FutureCatchExceptionDemo {
    public static void main(String[] args) {
        Callable<String> getSubString = new SubStringCallable();
        FutureTask<String> stringFutureTask = new FutureTask<String>(getSubString);
        Thread subStringThread = new Thread(stringFutureTask);
        subStringThread.start();
        try{
            System.out.println(stringFutureTask.get());
        }catch (Exception e){
            System.out.println("返回子字符串失败了,应该是截取越界!");
        }
    }
}

class SubStringCallable implements Callable<String>{

    @Override
    public String call() throws Exception {
        String fullInfoString = "我是AAA字符串,据说我要被截取一小段,然后返回....";
        String tmpSubString = fullInfoString.substring(15,30);
        return tmpSubString;
    }
}

call()方法包含 throws Exception 的能力,即当线程内部发生异常的时候可以抛出给外层线程进行捕获。主要是通过Future的get()方法得到call()方法的返回值,来进行外层的异常捕获。

//结果
返回子字符串失败了,应该是截取越界!

Process finished with exit code 0
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值