java多线程中的异常处理 |
您所在的位置:网站首页 › 同步代码块内的线程抛出异常 › java多线程中的异常处理 |
首先,我们要知道,在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 |