- 引言
- Sleep相关的异常
- 1 InterruptedException
- wait相关的异常
- 1 等待阶段调用中断方法异常
- 2 调用wait方法却没有对象锁
- 3 调用wait方法虽然是同步方法但是不是相应的对象锁
- join相关的异常
- 1 线程等待调用interrupt异常
- 捕捉异常
- 1给对象添加异常捕捉器
- 2 给线程类添加异常捕捉器相当于给全部对象添加异常捕捉
- 3 线程组内处理异常
- 4 自定义异常
1.引言
在本篇博客中主要记录一下:在多线程编程当中出现的异常,以及如何去捕捉异常。
2.Sleep相关的异常
2.1 InterruptedException
在这里我们首先要看一下Sleep中的InterruptedException
异常是如何产生的。
- 创建线程类
public class MyThread extends Thread {
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 在线程
sleep
阶段调用interrupt()
方法
public class App {
public static void main(String[] args) throws Exception {
MyThread td=new MyThread();
td.start();
//保证线程正在沉睡
Thread.sleep(1000);
td.interrupt();
}
}
- 产生异常
- 异常原因
当线程处于睡眠的情况下,不可以调用中断方法。
3.wait相关的异常
3.1 等待阶段调用中断方法异常
- 线程类
public class MyThread extends Thread {
private Object lock;
public MyThread(Object lock){
this.lock=lock;
}
public void run() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 线程等待阶段调用
interrupt()
方法
public class App {
public static void main(String[] args) throws Exception {
Object lock=new Object();
MyThread td=new MyThread(lock);
td.start();
Thread.sleep(1000);
td.interrupt();
}
}
- 运行异常
- 异常原因
当线程处于等待的情况下,不可以调用中断方法。
3.2 调用wait方法,却没有对象锁
- 创建线程类
public class MyThread extends Thread {
private Object lock;
public MyThread(Object lock) {
this.lock = lock;
}
public void run() {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 运行线程类
public class App {
public static void main(String[] args) throws Exception {
Object lock=new Object();
MyThread td=new MyThread(lock);
td.start();
}
}
- 产生异常
- 产生异常的原因
运行lock.wait();
方法的线程,没有获得lock
对象锁,注意一定要获取lock
对象锁
3.3 调用wait方法,虽然是同步方法,但是不是相应的对象锁
- 线程类
public class MyThread extends Thread {
private Object lock1;
private Object lock2;
public MyThread(Object lock1,Object lock2) {
this.lock1 = lock1;
this.lock2=lock2;
}
public void run() {
synchronized (lock2) {
try {
lock1.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 运行线程类
public class App {
public static void main(String[] args) throws Exception {
Object lock1=new Object();
Object lock2=new Object();
MyThread td=new MyThread(lock1,lock2);
td.start();
}
}
- 出现异常
- 异常原因
线程虽然获得了lock2
的对象锁,但是没有获得lock1
的对象锁
4.join相关的异常
我们之前提过:join的底层是通过wait方法实现的。也就是说当线程处于join方法等待时,是不可以调用interrupt()
方法
4.1 线程等待调用interrupt()异常
- 创建线程类
public class MyThread extends Thread {
public void run() {
try {
this.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- main方法
public class App {
public static void main(String[] args) throws Exception {
Object o=new Object();
MyThread td=new MyThread();
td.start();
Thread.sleep(1000);
td.interrupt();
}
}
- 出现异常
- 异常产生的原因
在线程等待的情况下调用了interrupt()
方法
5.捕捉异常
在多线程中如果出现了异常我们应该如何捕捉呢?比如我们的线程类是:
public class MyThread extends Thread {
public void run() {
String username=null;
//这里应该是空指针异常
System.out.println(username.trim());
}
}
5.1给对象添加异常捕捉器
- main方法
import java.lang.Thread.UncaughtExceptionHandler;
public class App {
public static void main(String[] args) throws Exception {
MyThread td=new MyThread();
td.setName("异常线程");
td.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
System.out.println("出现异常的线程是:"+t.getName());
System.out.println(e.toString());
}
});
td.start();
}
}
- 运行结果
5.2 给线程类添加异常捕捉器(相当于给全部对象添加异常捕捉)
- main方法
import java.lang.Thread.UncaughtExceptionHandler;
public class App {
public static void main(String[] args) throws Exception {
MyThread td=new MyThread();
td.setName("异常线程");
MyThread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
System.out.println("出现异常的线程是:"+t.getName());
System.out.println(e.toString());
}
});
td.start();
}
}
- 线程类
5.3 线程组内处理异常
线程组中的异常我们实现的功能为:如果组内某一个线程出现了异常,那么线程组内的所有线程都要停止
- 创建两个线程(线程A 有异常,线程B 无异常)
public class MyThreadA extends Thread {
public MyThreadA(ThreadGroup group) {
super(group,"MyThreadA");
}
public void run() {
String username=null;
//这里应该是空指针异常
System.out.println(username.trim());
}
}
public class MyThreadB extends Thread {
public MyThreadB(ThreadGroup group) {
super(group,"MyThreadB");
}
public void run() {
while(!this.isInterrupted())
{
System.out.println("线程组没有异常");
}
}
}
- 自定义我们的线程组
public class MyThreadGroup extends ThreadGroup{
public MyThreadGroup(String name) {
super(name);
}
public void uncaughtException(Thread t, Throwable e) {
this.interrupt();
super.uncaughtException(t, e);
}
}
- main函数
import java.lang.Thread.UncaughtExceptionHandler;
public class App {
public static void main(String[] args) throws Exception {
MyThreadGroup group=new MyThreadGroup("异常线程组");
MyThreadA tdA=new MyThreadA(group);
MyThreadB tdB=new MyThreadB(group);
tdA.start();
tdB.start();
}
}
- 运行结果(当线程组A出现异常之后,线程组B 也停止了。)
5.4 自定义异常
如果我们自定义我们的异常类型:实现UncaughtExceptionHandler
接口
import java.lang.Thread.UncaughtExceptionHandler;
public class ObjectUncaughtExceptionHandler implements UncaughtExceptionHandler{
public void uncaughtException(Thread t, Throwable e) {
//在这里写我们的异常处理
}
}