0040 Java学习笔记-多线程-线程run()方法中的异常
2016-12-09 12:06
543 查看
run()与异常
不管是Threade还是Runnable的run()方法都没有定义抛出异常,也就是说一条线程内部发生的checked异常,必须也只能在内部用try-catch处理掉,不能往外抛,因为线程是一个独立运行的代码片段,它的问题不能影响到其他线程如果run()内部抛出一个unchecked异常,这个线程可能会终止运行,这个异常也不能被主线程捕获,也影响不到其他线程的执行,比如下面的示例:
package testpack; import java.io.IOException; public class Test2 { public static void main(String[] args) throws InterruptedException{ try { new A("异常线程").start(); } catch(RuntimeException re) { System.out.println("主线程捕获到子线程的异常:"); //这里不会被执行,主线程不能捕获子线程的unchecked异常 re.printStackTrace(); } Thread.sleep(5); System.out.println("主线程照常执行"); //子线程终止,不影响主线程的正常执行 } } class A extends Thread{ A(String name){ super(name); } public void run(){ System.out.println("run()方法运行..."); for (int i=0;i<10;i++) { System.out.println(getName()+" 输出:"+i); if (i==3) { throw new RuntimeException("run内部抛出Runtime异常"); //第3个循环时,抛出一个unchecked异常 } } } }
输出:
run()方法运行...
异常线程 输出:0
异常线程 输出:1
异常线程 输出:2
异常线程 输出:3
Exception in thread "异常线程" java.lang.RuntimeException: run内部抛出Runtime异常 at testpack.A.run(Test2.java:26) //子线程抛出unchecked异常,不能被主线程catch到,线程终止执行。这里的输出来源于ThreadGroup的uncaughtException()方法
主线程照常执行 //子线程终止后,不影响主线程执行
Thread.UncaughtExceptionHandler异常处理器
Thread有一个静态内部接口,UncaughtExceptionHandler,该接口用来定义未处理异常处理器,只有一个方法void uncaughtException(Thread t,Throwable e)可以自己定义一个线程处理器,然后将其绑定到一个线程实例、Thread上,ThreadGroup已经实现了void uncaughtException(Thread t,Throwable e)方法,如果要更改的话,就继承ThreadGroup类然后重写该方法
将一个未处理异常处理器绑到线程对象上:调用该线程对象的setUncaughtExceptionHandler()
绑到Thread上:调用Thread的静态方法Thread.setDefaultUncaughtExceptionHandler()
未处理异常处理器的调用顺序
先找该线程实例是否有处理器再交给所属线程组的uncaughtException()方法
严格的说,这个方法只是个中介,分下面三步走
如果还有父线程组,则交给父线程组的uncaughtException()方法
交给Thread的Thread.getDefaultUncaughtExceptionHandler()返回的Thread默认处理器
最后看该线程是不是ThreadDeath对象,是的话,不做处理;不是的话,先用System.err输出哪个线程上有Exception,然后将异常跟踪站信息打印到System.err,线程结束
看示例:
package testpack; import java.lang.Thread.UncaughtExceptionHandler; public class Test2 { public static void main(String[] args) throws InterruptedException{ ExHandler eh1=new ExHandler("Thread默认异常处理器"); //定义一个异常处理器,后面绑到Thread上 ExHandler eh2=new ExHandler("线程实例异常处理器"); //后面绑到线程实例上 Thread.setDefaultUncaughtExceptionHandler(eh1); //将eh1处理器绑到Thread上 A a=new A("异常线程"); a.setUncaughtExceptionHandler(eh2); //标记㈠。将eh2绑到线程实例上 a.start(); } } class A extends Thread{ A(ThreadGroup tg,String name){ super(tg,name); } A(String name){ super(name); } public void run(){ System.out.println("run()方法运行..."); for (int i=0;i<10;i++) { System.out.println(getName()+" 输出:"+i); if (i==3) { int x=5/0; //i==3时,抛出unchecked异常 } } } } class ExHandler implements UncaughtExceptionHandler{ //自定义一个未处理异常处理器 private String name; ExHandler(String name){ this.name=name; } public void uncaughtException (Thread t,Throwable e){ System.out.println("这是:"+name); System.out.println("线程: "+t.getName()+" 异常: "+e.getMessage()); } }
输出:
run()方法运行...
异常线程 输出:0
异常线程 输出:1
异常线程 输出:2
异常线程 输出:3
这是:线程实例异常处理器 //调用了线程实例上的异常处理器
线程: 异常线程 异常: / by zero //程序结束
将标记㈠处的代码注释掉,输出如下:
run()方法运行...
异常线程 输出:0
异常线程 输出:1
异常线程 输出:2
异常线程 输出:3
这是:Thread默认异常处理器 //调用了Thread上的默认处理器,“异常线程”属于main线程组,父线程组是system,
线程: 异常线程 异常: / by zero
其他
最近发现一个做笔记的地方,蚂蚁笔记:https://leanote.com,支持Markdown,还可以把一篇笔记或一个笔记本公开为博客,可以绑定二级域名或者自定义域名,可以导出为PDF,支持团队协作,甚至是开源的,可以将其部署在自己的服务器上,是一个挺不错的应用本篇笔记也发布在leanote:在这里
这是我的邀请链接,如果想注册,可以通过该链接,你我都可以获得30天的旗舰版时间
相关文章推荐
- JAVA学习笔记--多线程(二)线程常用方法
- Java学习笔记63. 由开发者抛出异常的两种方法 -- throws 和 throw
- [置顶] Java 多线程 学习笔记(二)停止线程的几种方法
- Effective Java 学习笔记(第62条:每个方法抛出的异常都要有文档)
- 学习笔记_java.lang.reflect.Field_解决IllegalAccessException异常的方法
- JAVA学习笔记26——异常机制2:常见异常+异常处理其余两种方法+自定义异常
- Java学习笔记—多线程(Java线程常用方法总结)
- Java学习笔记67. 创建多线程的方法 -- 通过继承thread类创建多线程
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
- Java开发学习笔记:Java实现多线程的方法
- java多线程学习笔记——yield()、wait()、sleep()等方法
- 学习笔记_毕向东 Java_内部类_异常_多线程 2014.7.15
- 学习java多线程的笔记1--Thread(Runnable t)与重写run()方法等
- JAVA学习笔记25——异常机制1:Exception简介+异常处理的try_catch_finally方法
- JNI学习笔记5——本地方法处理java数组/引用问题/缓存jfieldID/jmethodID
- JAVA异常学习笔记
- java多线程学习一:实现多线程的两种方法
- JAVA多线程学习笔记
- [零散篇]Java学习笔记---Java的Socket网络编程以及多线程
- Java6学习笔记55——多线程编程——线程的创建方法1