例外(スレッド)調査ノートをキャッチ

スレッドの性質上、スレッドからエスケープする例外をキャッチすることはできません。例外がタスクのrun()メソッドをエスケープすると、この間違った例外をキャッチするために特別な手順が実行されない限り、例外はコンソールに伝播されます。java SE5より前は、スレッドグループを使用して例外をキャッチできましたが、java SE5では、Executorを使用してこの問題を解決できます

class ExceptionThread implements Runnable{
    
    
	public void run() {
    
    
		throw new RuntimeException();
	}
}
public class NaiveExceptionHandling {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		try {
    
    
            ExecutorService exec=Executors.newCachedThreadPool();
            exec.execute(new ExceptionThread());
		}catch(RuntimeException e) {
    
    
			System.out.println("Exception has been handled");
		}
	}

}
/*
Exception in thread "pool-1-thread-1" java.lang.RuntimeException
at demo.ExceptionThread.run(NaiveExceptionHandling.java:8)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
*/

上記のプログラムを実行すると、ウィンドウに表示され、「例外が処理されました」が出力されないため、スレッドでスローされた例外をtry-catch句でキャッチできません。

この問題を解決するには、Executorがスレッドを生成する方法を変更する必要があります。
Thread.UncaughtExceptionHandlerは、java SE5の新しいインターフェイスであり、各Threadオブジェクトに例外ハンドラーをアタッチできます。Thread.UncaughtExceptionHandler.uncaughtException()は、キャッチされなかった例外が原因でスレッドが終了しようとしているときに呼び出されます。

class ExceptionThread2 implements Runnable{
    
    
	public void run() {
    
    
		Thread t=Thread.currentThread();
		System.out.println("run() by "+t);
		System.out.println("ek = "+t.getUncaughtExceptionHandler());
		throw new RuntimeException();
	}
}
class MyUncaughtExceptionHandler implements UncaughtExceptionHandler{
    
    

	@Override
	public void uncaughtException(Thread t, Throwable e) {
    
    
		// TODO Auto-generated method stub
		System.out.println("caught "+e);
	}
	
}
class HandlerThreadFactory implements ThreadFactory{
    
    

	@Override
	public Thread newThread(Runnable r) {
    
    
		// TODO Auto-generated method stub
		System.out.println(this+" creating new Thread");
		Thread t=new Thread(r);
		System.out.println("created "+t);
		t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
		System.out.println("eh = "+t.getUncaughtExceptionHandler());
		return t;
	}
	
}
public class CaptureUncaughtException {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
        ExecutorService exec=Executors.newCachedThreadPool(new HandlerThreadFactory());
        exec.execute(new ExceptionThread2());
	}

}
/*
demo.HandlerThreadFactory@4e25154f creating new Thread
created Thread[Thread-0,5,main]
eh = demo.MyUncaughtExceptionHandler@70dea4e
run() by Thread[Thread-0,5,main]
ek = demo.MyUncaughtExceptionHandler@70dea4e
demo.HandlerThreadFactory@4e25154f creating new Thread
created Thread[Thread-1,5,main]
eh = demo.MyUncaughtExceptionHandler@3670f81
caught java.lang.RuntimeException
*/

上記のプログラムは、新しいタイプの作成(カスタマイズされたThreadFactoryを書き込むことによって、あなたはExcecutorによって作成されたスレッドの属性(背景、優先順位、名前)をカスタマイズすることができます。)ThreadFactoryをそれが各新しく作成されたスレッド・オブジェクトにスレッドを添付します。 UncaughtExceptionHandlerこのファクトリをExecutorsに渡して、新しいExecutorServiceメソッドを作成します。

コード内のどこでも同じ例外ハンドラーを使用する場合、より簡単な方法は、Threadクラスに静的フィールドを設定し、このハンドラーをデフォルトのキャッチ例外ハンドラーとして設定することです。
Thread.setDeflautUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
このハンドラーは、スレッド固有のキャッチされていない例外ハンドラーがない場合にのみ呼び出されます。つまり、上記のメソッドが最後に呼び出されます。

おすすめ

転載: blog.csdn.net/weixin_43916777/article/details/104242892
おすすめ