子线程中的异常捕获

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ytuglt/article/details/83994224

根据java线程的本质,当一个线程抛出异常时,在主线程中加try catch 是无法捕获到其抛出的异常的,如下面代码所示:

   private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onClickBtn(View view) {
        try {
            Thread thread = new Thread(new ExceptionThread());
            ExecutorService service = Executors.newCachedThreadPool();
            service.execute(thread);
        } catch (Exception e) {
            Log.d(TAG, "onClickBtn: catch the excepiton");
            e.printStackTrace();
        }
    }

    class ExceptionThread implements Runnable {

        @Override
        public void run() {
            Log.d(TAG, "run: start to throw exception");
            throw new RuntimeException();
        }
    }

点击按钮应用就会crash,异常log如下:

2018-11-12 16:32:08.106 32514-32545/com.air.testexceptioncatchinthead D/MainActivity: run: start to throw exception
    
    --------- beginning of crash
2018-11-12 16:32:08.113 32514-32545/com.air.testexceptioncatchinthead E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
    Process: com.air.testexceptioncatchinthead, PID: 32514
    java.lang.RuntimeException
        at com.air.testexceptioncatchinthead.MainActivity$ExceptionThread.run(MainActivity.java:37)
        at java.lang.Thread.run(Thread.java:764)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

从上面实验中可以看到,在有多个线程时,另外一个线程是无法捕获到另外一个线程抛出的异常的。

那么这种异常如何捕获呢,java 在JDK5中引入了UncaughtExceptionHandler接口,实现如下:

class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            Log.d(TAG, "uncaughtException: caught " + t + e.toString());
            e.printStackTrace();
        }
    }
public void onClickBtn(View view) {
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        new Thread(new ExceptionThread()).start();
    }

此时点击,就会发现app已经不会crash了,完整代码如下:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onClickBtn(View view) {
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        new Thread(new ExceptionThread()).start();
    }

    class ExceptionThread implements Runnable {

        @Override
        public void run() {
            Log.d(TAG, "run: start to throw exception");
            throw new NullPointerException();
        }
    }

    class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            Log.d(TAG, "uncaughtException: caught " + t + e.toString());
            e.printStackTrace();
        }
    }
} 

注意:JVM设计源于这样一种理念,线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部。基于这样的理念,在java中线程方法的异常都应该在线程内部处理掉,这种外部捕获异常的方案通常情况下不应该使用

猜你喜欢

转载自blog.csdn.net/ytuglt/article/details/83994224