java多线程中的异常处理

您所在的位置:网站首页 同步代码块内的线程抛出异常 java多线程中的异常处理

java多线程中的异常处理

2024-03-10 19:05| 来源: 网络整理| 查看: 265

首先,我们要知道,在Java中,线程中的异常是不能抛出到调用该线程的外部方法中捕获的。

为什么不能抛出到外部线程捕获? 因为线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部。”基于这样的设计理念,在Java中,线程方法的异常都应该在线程代码边界之内(run方法内)进行try catch并处理掉。换句话说,我们不能捕获从线程中逃逸的异常。

怎么进行的限制? 通过java.lang.Runnable.run()方法声明(因为此方法声明上没有throw exception部分)进行了约束。

如果在线程中抛出了线程会怎么样? 线程会立即终结。 放在线程池中的线程要捕获异常,如果直接抛出异常,每次都会创建线程,也就等于线程池没有发挥作用,如果大并发下一直创建线程可能会导致JVM挂掉.

现在我们可以怎样捕获线程中的异常? Java中在处理异常的时候,通常的做法是使用try-catch-finally来包含代码块,但是Java自身还有一种方式可以处理——使用UncaughtExceptionHandler。它能检测出某个线程由于未捕获的异常而终结的情况。当一个线程由于未捕获异常而退出时,JVM会把这个事件报告给应用程序提供的UncaughtExceptionHandler异常处理器(这是Thread类中的接口):

//Thread类中的接口 public interface UncaughtExceptionHanlder {     void uncaughtException(Thread t, Throwable e); }

JDK5之后允许我们在每一个Thread对象上添加一个异常处理器UncaughtExceptionHandler 。Thread.UncaughtExceptionHandler.uncaughtException()方法会在线程因未捕获的异常而面临死亡时被调用。

首先要先定义一个异常捕获器:

public class MyUnchecckedExceptionhandler implements UncaughtExceptionHandler {     @Override     public void uncaughtException(Thread t, Throwable e) {         System.out.println("捕获异常处理方法:" + e);     } }

方法1. 创建线程时设置异常处理Handler

Thread t = new Thread(new ExceptionThread()); t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler()); t.start();

方法2. 使用Executors创建线程时,还可以在ThreadFactory中设置

ExecutorService exec = Executors.newCachedThreadPool(new ThreadFactory(){             @Override             public Thread newThread(Runnable r) {                 Thread thread = new Thread(r);                 thread.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());                 return thread;             } }); exec.execute(new ExceptionThread());

不过,上面的结果能证明:通过execute方式提交的任务,能将它抛出的异常交给异常处理器。如果改成submit方式提交任务,则异常不能被异常处理器捕获,这是为什么呢?查看源码后可以发现,如果一个由submit提交的任务由于抛出了异常而结束,那么这个异常将被Future.get封装在ExecutionException中重新抛出。所以,通过submit提交到线程池的任务,无论是抛出的未检查异常还是已检查异常,都将被认为是任务返回状态的一部分,因此不会交由异常处理器来处理。

java.util.concurrent.FutureTask 源码

public V get() throws InterruptedException, ExecutionException {     int s = state;     if (s = CANCELLED)//如果任务被取消,调用get则报CancellationException         throw new CancellationException();     throw new ExecutionException((Throwable)x);//执行异常,则抛出ExecutionException }

方法3. 使用FetureTask来捕获异常(线程池中submit时一样)

//1.创建FeatureTask FutureTask futureTask = new FutureTask(new Callable() {     @Override     public Integer call() throws Exception {         return 1/0;     } }); //2.创建Thread Thread thread = new Thread(futureTask); //3.启动线程 thread.start(); try {     Integer result = futureTask.get(); } catch (InterruptedException e) {     e.printStackTrace(); } catch (ExecutionException e) {     //4.处理捕获的线程异常 }

原文链接:https://blog.csdn.net/pange1991/article/details/82115437

也可以参考

https://www.jianshu.com/p/849d490d013d https://blog.csdn.net/breakout_alex/article/details/106229571



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3