Behandlung von Thread-Ausnahmen

1. Gründe für die Notwendigkeit von UncaughtExceptionHandler

  • Ausnahmen können leicht im Hauptthread gefunden werden, z. B. Drucken von Stapelinformationen, der untergeordnete Thread jedoch nicht. Das Codebeispiel wird in der ExceptionInChildThread-Klasse angezeigt.
  • Der untergeordnete Thread kann die Ausnahme mit der herkömmlichen try catch-Methode nicht abfangen. Das Codebeispiel wird in der CannotCatchDirectly-Klasse angezeigt.
  • Wenn die Ausnahme nicht abgefangen wird, löst der untergeordnete Thread eine Ausnahme aus und wird nicht mehr ausgeführt, wodurch die Robustheit des Systems zerstört wird.
/**
 * 描述:研究单线程抛出时的处理情况
 */
public class ExceptionInChildThread implements Runnable {
    
    
    @Override
    public void run() {
    
    
        throw new RuntimeException();
    }

    public static void main(String[] args) {
    
    
        ExceptionInChildThread exceptionInChildThread = new ExceptionInChildThread();
        Thread t = new Thread(exceptionInChildThread);
        t.start();
        for (int i = 1; i < 10; i++) {
    
    
            System.out.println("正在打印" + i);
        }
    }
}

Die Ergebnisse der Programmausführung sind wie folgt: Sie können sehen, dass die Stapelinformationen verstreut sind und an die Konsole ausgegeben werden, was nicht sehr praktisch ist.

Exception in thread "Thread-0" java.lang.RuntimeException
正在打印1
正在打印2
	at com.leichuangkj.threads.ExceptionInChildThread.run(ExceptionInChildThread.java:6)
正在打印3
	at java.lang.Thread.run(Thread.java:748)
正在打印4
正在打印5
正在打印6
正在打印7
正在打印8
正在打印9
/**
 * 描述:证明线程的异常不能用传统方法捕获
 * 1.不加try catch抛出4个异常,都带线程名字
 * 2.加了try catch,期望捕获到第一个线程的异常,线程234不应该被捕获,期待打印出Caught Exception
 * 3.执行时发现,根本没有Caught Exception,线程234依然运行并且抛出异常
 */
public class CannotCatchDirectly implements Runnable {
    
    
    @Override
    public void run() {
    
    
        throw new RuntimeException();
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        CannotCatchDirectly cannotCatchDirectly = new CannotCatchDirectly();
        try {
    
    
            Thread t1 = new Thread(cannotCatchDirectly, "MyThread1");
            t1.start();
            Thread.sleep(1000);
            Thread t2 = new Thread(cannotCatchDirectly, "MyThread2");
            t2.start();
            Thread.sleep(1000);
            Thread t3 = new Thread(cannotCatchDirectly, "MyThread3");
            t3.start();
            Thread.sleep(1000);
            Thread t4 = new Thread(cannotCatchDirectly, "MyThread4");
            t4.start();
            Thread.sleep(1000);
        } catch (RuntimeException exception) {
    
    
            System.out.println(Thread.currentThread().getName() + "抛出异常");
        }
    }
}

Das Ergebnis der Programmausführung lautet wie folgt: Wenn MyThread1 eine Ausnahme auslöst, sollte es in den catch-Zweig eintreten und das Programm beenden. Tatsächlich gibt es jedoch keine, das Programm wird weiterhin ausgeführt, und die 4 untergeordneten Threads lösen jeweils Ausnahmen aus, was zeigt, dass die untergeordneten Thread-Ausnahmen nicht mit try catch abgefangen werden.

Exception in thread "MyThread1" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "MyThread2" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "MyThread3" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "MyThread4" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)

2. Analyse des UncaughtExceptionHandler-Quellcodes

public class ThreadGroup implements Thread.UncaughtExceptionHandler {
    
    
	public void uncaughtException(Thread t, Throwable e) {
    
    
		//默认情况下parent是null
        if (parent != null) {
    
    
            parent.uncaughtException(t, e);
        } else {
    
    
        	//设置全局handler进行处理
            Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
    
    
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
    
    
            	//全局handler不存在则输出异常堆栈
                System.err.print("Exception in thread \"" + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }
}

3. Global Exception Handler

/**
 * 描述:自定义UncaughtExceptionHandler
 */
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    
    
    private String name;

    MyUncaughtExceptionHandler(String name){
    
    
        this.name = name;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
    
    
        System.out.println(t.getName() + "捕获异常,异常信息" + e.toString());
    }
}
/**
 * 描述:使用自定义的UncaughtExceptionHandler
 */
class UseOwnUncaughtExceptionHandler implements Runnable {
    
    
    @Override
    public void run() {
    
    
        throw new RuntimeException();
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler("捕获器"));
        UseOwnUncaughtExceptionHandler useOwnUncaughtExceptionHandler = new UseOwnUncaughtExceptionHandler();
        Thread t1 = new Thread(useOwnUncaughtExceptionHandler, "MyThread1");
        t1.start();
        Thread.sleep(1000);
        Thread t2 = new Thread(useOwnUncaughtExceptionHandler, "MyThread2");
        t2.start();
        Thread.sleep(1000);
        Thread t3 = new Thread(useOwnUncaughtExceptionHandler, "MyThread3");
        t3.start();
        Thread.sleep(1000);
        Thread t4 = new Thread(useOwnUncaughtExceptionHandler, "MyThread4");
        t4.start();
        Thread.sleep(1000);
    }
}

Das Ergebnis der Programmausführung ist unten dargestellt. Die von den 4 untergeordneten Threads ausgelösten Ausnahmen werden alle abgefangen.

MyThread1捕获异常,异常信息java.lang.RuntimeException
MyThread2捕获异常,异常信息java.lang.RuntimeException
MyThread3捕获异常,异常信息java.lang.RuntimeException
MyThread4捕获异常,异常信息java.lang.RuntimeException

Ich denke du magst

Origin blog.csdn.net/Jgx1214/article/details/108372900
Empfohlen
Rangfolge