• 引言
  • 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();

    }

}
  • 产生异常

java 线程增多问题排查 java线程出现异常_java 线程增多问题排查

  • 异常原因
    当线程处于睡眠的情况下,不可以调用中断方法。

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();

    }

}
  • 运行异常

java 线程增多问题排查 java线程出现异常_java_02

  • 异常原因
    当线程处于等待的情况下,不可以调用中断方法。

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();
    }

}
  • 产生异常

java 线程增多问题排查 java线程出现异常_多线程_03

  • 产生异常的原因
    运行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();
    }

}
  • 出现异常

java 线程增多问题排查 java线程出现异常_对象_04

  • 异常原因
    线程虽然获得了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();
    }

}
  • 出现异常

java 线程增多问题排查 java线程出现异常_java 线程增多问题排查_05

  • 异常产生的原因
    在线程等待的情况下调用了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();
    }

}
  • 运行结果

java 线程增多问题排查 java线程出现异常_java_06

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();
    }

}
  • 线程类

java 线程增多问题排查 java线程出现异常_java 线程增多问题排查_07

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 也停止了。)

java 线程增多问题排查 java线程出现异常_java 线程增多问题排查_08

5.4 自定义异常

如果我们自定义我们的异常类型:实现UncaughtExceptionHandler接口

import java.lang.Thread.UncaughtExceptionHandler;


public class ObjectUncaughtExceptionHandler  implements UncaughtExceptionHandler{

    public void uncaughtException(Thread t, Throwable e) {
        //在这里写我们的异常处理   
    }

}