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
Java线程-异常处理的更多相关文章
- java线程异常处理方法
		
工作中常发现有些程序发生异常但却没有错误日志,原因就是一些开发线程异常处理错误,导致程序报错但异常信息打印到堆栈上,不好在生产环境中定位问题. 在java多线程程序中,所有线程都不允许抛出未捕获的ch ...
 - JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理
		
本文记录: 1,使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务的过程,讨论了在任务周期执行过程中出现了异常,会导致周期任务失败. 2 ...
 - Java线程并发:知识点
		
Java线程并发:知识点 发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用. 逃逸:在对象尚未准备 ...
 - 捕获Java线程池执行任务抛出的异常
		
捕获Java线程池执行任务抛出的异常Java中线程执行的任务接口java.lang.Runnable 要求不抛出Checked异常, public interface Runnable { publi ...
 - java 线程基本概念 可见性 同步
		
开发高性能并发应用不是一件容易的事情.这类应用的例子包括高性能Web服务器.游戏服务器和搜索引擎爬虫等.这样的应用可能需要同时处理成千上万个请求.对于这样的应用,一般采用多线程或事件驱动的架构.对于J ...
 - Java线程组(ThreadGroup)使用
		
JDK 对线程组类注释: A thread group represents a set of threads. In addition, a thread group can also includ ...
 - Java开发知识之Java的异常处理
		
Java开发知识之Java的异常处理 一丶异常概述 在讲解异常之前,我们要搞清楚.什么是异常. 通俗理解就是我们编写的程序出问题了.进行处理的一种手段. 比如我们的QQ.有的时候就崩溃了.比如出现xx ...
 - 异常处理器详解 Java多线程异常处理机制  多线程中篇(四)
		
在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...
 - JAVA 线程池之Callable返回结果
		
本文介绍如何向线程池提交任务,并获得任务的执行结果.然后模拟 线程池中的线程在执行任务的过程中抛出异常时,该如何处理. 一,执行具体任务的线程类 要想 获得 线程的执行结果,需实现Callable接口 ...
 
随机推荐
- QCanvasItem介绍-QT3
			
QCanvasItem类提供一个在QCanvas上的抽象图形对象. 各种QCanvasItem子类提供立即可用的行为.这个类是一个纯粹的抽象超类,它提供了在所有具体的canvas项目类中共享的行为.Q ...
 - 一种基于http协议的敏感数据传输方案
			
最近公司需要通过公网与其它平台完成接口对接,但是基于开发时间和其它因素的考虑,本次对接无法采用https协议实现.既然不能用https协议,那就退而求其次采用http协议吧! 那么问题来了!在对接的过 ...
 - .NET使用Office Open XML导出超大数量数据到 Excel
			
我相信很多人在做项目的都碰到过Excel数据导出的需求,我从最开始使用最原始的HTML拼接(将需要导出的数据拼接成TABLE标签)到后来happy的使用开源的NPOI, EPPlus等开源组件导出EX ...
 - 设计模式六大原则(PHP)
			
设计模式的目的是为了更好的代码重用性,可读性,可靠性和可维护性.常用的六大设计模式有:单一职责原则(SRP),里氏替换原则(LSP),依赖倒转原则(DIP),接口隔离原则(ISP),迪米特法则(LOD ...
 - 使用socket实现的ftp文件传输服务器
			
服务端: # encoding:utf-8 # Author:"richie" # Date:8/23/2017 from socket import * import pickl ...
 - Android开发之漫漫长途 XI——从I到X的小结
			
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
 - 新手必须掌握的Linux命令
			
一.命令组成 一个完整的命令通常由 命令名称 [命令参数] [命令对象] 组成. 注意:命令名称.命令参数.命令对象之间用空格键隔开. 二.系统工作命令 查看主机名称 echo $HOSTNAME ...
 - Codeforces 626D Jerry's Protest(暴力枚举+概率)
			
D. Jerry's Protest time limit per test:2 seconds memory limit per test:256 megabytes input:standard ...
 - HDU2824-The Euler function-筛选法求欧拉函数+求和
			
欧拉函数: φ(n)=n*(1-1/p1)(1-1/p2)....(1-1/pk),其中p1.p2-pk为n的所有素因子.比如:φ(12)=12*(1-1/2)(1-1/3)=4.可以用类似求素数的筛 ...
 - hdu_1042(模拟大数乘法)
			
计算n! #include<cstring> #include<cstdio> using namespace std; ]; int main() { int n; whil ...