在java多线程程序中,所有线程都不允许抛出未捕获的checked exception(比如sleep时的InterruptedException)也就是说各个线程需要自己把自己的checked exception处理掉。

这句话怎么理解,最简单的看下图,也就是不能在Runnable的run方法上抛出异常,必须在里面捕获。

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

看下面的例子:

public class ExceptionTest {

    public static void main(String[] args) {

        try {
new Thread(new ExceptionTask()).start();
} catch (Exception e) {
System.out.println("注意看我是否能打印。。。");
e.printStackTrace();
}
} } class ExceptionTask implements Runnable { @Override
public void run() {
System.out.println("".substring(0, 10));
} }

打印结果

Exception in thread "Thread-0" java.lang.StringIndexOutOfBoundsException: String index out of range: 10
at java.lang.String.substring(Unknown Source)
at com.actuator.ExceptionTask.run(ExceptionTest.java:21)
at java.lang.Thread.run(Unknown Source)

从运行结果中,我们可以看到的是,"Thread-0"线程里的异常在main线程中没有catch到。

问题来了,我们如果需要捕获"Thread-0"线程的unchecked异常时该怎么办?Java SE5之后,我们可以通过Executor来解决这个问题。

Thread.UncaughtExceptionHandler是java SE5中的新接口,它允许我们在每一个Thread对象上添加一个异常处理器。(UncaughtExceptionHandler)。Thread.UncaughtExceptionHandler.uncaughtException()方法会在线程因未捕获的异常而面临死亡时被调用。

下面这个例子简单的演示了如何使用UncaughtExceptionHandler。

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; public class ExceptionTest { public static void main(String[] args) { // 下面有两种方式来执行线程 // 第一种,非线程池写法
Thread t = new Thread(new ExceptionTask());
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("线程"+t.getName()+"捕获到异常:"+e.getMessage());
}
});
t.start(); // 第二种,线程池写法
ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("线程"+t.getName()+"捕获到异常:"+e.getMessage());
}
});
return t;
}
});
executorService.execute(new ExceptionTask()); } } class ExceptionTask implements Runnable { @Override
public void run() {
System.out.println("".substring(0, 10));
} }

两个执行结果一样

线程Thread-0捕获到异常:String index out of range: 10

关于java多线程中异常捕获的理解的更多相关文章

  1. 转载:Java多线程中join方法的理解

    转载自:http://uule.iteye.com/blog/1101994 thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A ...

  2. Java多线程中join方法的理解

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B. t.join( ...

  3. Java多线程中的常用方法

    本文将带你讲诉Java多线程中的常用方法   Java多线程中的常用方法有如下几个 start,run,sleep,wait,notify,notifyAll,join,isAlive,current ...

  4. Java正则表达式中的捕获组的概念及相关API使用

    要弄清这三个方法,首先要弄清Java正则表达式中的捕获组的概念.捕获组也就是Pattern中以括号对“()”分割出的子Pattern.至于为什么要用捕获组呢,主要是为了能找出在一次匹配中你更关心的部分 ...

  5. java多线程中的三种特性

    java多线程中的三种特性 原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行. 如果一个操作时原子性的,那么多线程并 ...

  6. java 多线程中的wait方法的详解

    java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...

  7. java多线程中并发集合和同步集合有哪些?区别是什么?

    java多线程中并发集合和同步集合有哪些? hashmap 是非同步的,故在多线程中是线程不安全的,不过也可以使用 同步类来进行包装: 包装类Collections.synchronizedMap() ...

  8. java多线程中最佳的实践方案是什么?

    java多线程中最佳的实践方案是什么? 给你的线程起个有意义的名字.这样可以方便找bug或追踪.OrderProcessor, QuoteProcessor or TradeProcessor 这种名 ...

  9. Java多线程中的竞争条件、锁以及同步的概念

    竞争条件 1.竞争条件: 在java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生“竞争条件”的现象.这种现象产生的根本原因是因为多个线程在对同一个数据进行操作,此时对该数据的操作 ...

随机推荐

  1. P1967 货车运输

    P1967 货车运输最大生成树+lca+并查集 #include<iostream> #include<cstdio> #include<queue> #inclu ...

  2. Kafka、RabbitMQ、RocketMQ等消息中间件的对比 —— 消息发送性能和区别

    https://blog.csdn.net/yunfeng482/article/details/72856762

  3. PHP学习笔记 ThinkPHP

    //检测文件是否存在 if(!file_exists(dirname(__FILE__)."/Bo/Admin/Conf/config.php")) { header('Locat ...

  4. vuex那些事儿

    vuex适用于大型单页应用.每一个Vuex应用的核心就是store(仓库),store中储存大量状态,Vuex的状态存储是响应式的.vuex使用单一状态树,一个对象包含了全部的应用层级状态,每个应用仅 ...

  5. [Python]Marshmallow 代码

    schema.dump和schema.load schema.dump()方法返回一个MarshResult的对象,marshmallow官方API说dump和load方法返回的都是dict对象,但查 ...

  6. HDU 5985 Lucky Coins 数学

    Lucky Coins 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5985 Description Bob has collected a lot ...

  7. Docker技术快速精通指南

    doctor专业网站:http://www.dockerinfo.net/ Docker中文文档 csdn 的docker专栏: Docker技术快速精通指南

  8. [Web 前端] qs.parse()、qs.stringify()使用方法

    cp from : https://blog.csdn.net/suwu150/article/details/78333452 qs是一个npm仓库所管理的包,可通过npm install qs命令 ...

  9. Go web编程实例

    1. go web编程入门 记录个web编程例子方便以后使用. 主要有: chan的使用(带缓存,不带缓存) client发起get/post请求 server解析get/post请求参数 http. ...

  10. 关于jmeter命令行执行.jmx文件出现Error in NonGUIDriver java.lang.RuntimeException: Could not find the TestPlan c