关于多线程的异常处理

我们首先说一说在线程池中的异常处理。异常能否被抛出和捕捉和线程的返回有很大关系。像Runable()没有返回值自然就无法捕获和处理异常,如果时Callable()这类有返回值的线程我们就可以对它进行处理。

线程池中的异常处理

在多线程中我们对任务的提交方式决定了我们对线程中异常处理的不同。多线程中分别由submit提交和execute()提交任务的两种方式。

execute和submit的区别
1 提交任务的类型:
execute和submit都属于线程池的方法,execute只能提交Runnable类型的任务、
submit既能提交Runnable类型任务也能提交Callable类型任务。
2 异常:
execute会直接抛出任务执行时的异常,可以用try、catch来捕获,和普通线程的处理方式完全一致
submit会吃掉异常,可通过Future的get方法将任务执行时的异常重新抛出。
3 返回值:
execute()没有返回值
submit有返回值,所以需要返回值的时候必须使用submit .

使用submit处理异常

 ExecutorService threadPool = Executors.newFixedThreadPool(2);
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                int a = 1/0 ;
            }
        });
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                int a = 1/0 ;
            }
        });

使用submit异常被吃掉,如果需要处理异常需要通过get()方法得到Future类型的结果 如下所示:

 ExecutorService threadPool = Executors.newFixedThreadPool(2);
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                int a = 1/0 ;
            }
        }).get(); // 异常被抛出
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                int a = 1/0 ;
            }
        }); // 异常被吃掉
    }

使用execute提交任务处理异常

 ExecutorService threadPool = Executors.newFixedThreadPool(2);
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                int a = 1/0 ;
            }
        });
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                int a = 1/0 ;
            }
        });

异常直接被抛出

Exception in thread "pool-1-thread-1" Exception in thread "pool-1-thread-2" java.lang.ArithmeticException: / by zero
	at com.zkdx.shokai.modules.report.Test$1.run(Test.java:27)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
java.lang.ArithmeticException: / by zero
	at com.zkdx.shokai.modules.report.Test$2.run(Test.java:33)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

用try_catch可直接捕获异常

ExecutorService threadPool = Executors.newFixedThreadPool(2);
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    int a = 1 / 0;
                }catch (Exception e){
                    System.out.println(
                            "除0异常");
                }
            }
        });
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                int a = 1/0 ;
            }
        });
除0异常
Exception in thread "pool-1-thread-2" java.lang.ArithmeticException: / by zero
	at com.zkdx.shokai.modules.report.Test$2.run(Test.java:37)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

单线程中的异常处理

在单线程中处理异常的通用方式是使用Thead的setUncaughtExceptionHandler方法,当线程内部出现异常时会找到该方法并进行异常处理。

 Thread  thread = new Thread(new Runnable() {
            @Override
            public void run() {
                    int a = 1/0 ;
            }
        });
        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("除零异常");
            }
        });
        thread.start();
    }

你可能感兴趣的:(面试准备,java,数据库)