当前位置: 首页 > news >正文

网站建设意义/四川seo平台

网站建设意义,四川seo平台,哈尔滨招标信息网,长沙3合1网站建设公司本文为joshua317原创文章,转载请注明:转载自joshua317博客 多线程中如何进行异常处理? - joshua317的博客 一、Thread的默认异常处理 线程不允许抛出未捕获的checked exception(比如sleep时的InterruptedException),也就是说各…

本文为joshua317原创文章,转载请注明:转载自joshua317博客 多线程中如何进行异常处理? - joshua317的博客

一、Thread的默认异常处理

线程不允许抛出未捕获的checked exception(比如sleep时的InterruptedException),也就是说各个线程需要自己把自己的checked exception处理掉。我们可以查看一下Thread类的run()方法声明,方法声明上没有对抛出异常进行任何约束。

    //Thread类中@Overridepublic void run() {if (target != null) {target.run();}}//Runnable接口中public abstract void run();

JVM的这种设计源自于这样一种理念:“线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部。”基于这样的设计理念,在Java中,线程方法的异常(无论是checked exception还是unchecked exception),都应该在线程代码边界之内(run方法内)进行try catch并处理掉。换句话说,我们不能捕获从线程中逃逸的异常。

二、未捕获的异常如何处理的

一个异常被抛出后,如果没有被捕获处理,则会一直向上抛。异常一旦被Thread.run() 抛出后,就不能在程序中对异常进行捕获,最终只能由JVM捕获。

package com.joshua317;public class ThreadException {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();}
}class MyThread extends Thread {@Overridepublic void run(){System.out.println("线程名:" + Thread.currentThread().getName());//发生异常int i = 1 / 0;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}
}

接下来我们尝试对异常进行捕获,看看是否能捕获到

package com.joshua317;public class ThreadException {public static void main(String[] args) {try {MyThread myThread = new MyThread();myThread.start();}catch (Exception e) {System.out.println("捕获线程抛出的异常!" + e.getMessage());}}
}class MyThread extends Thread {@Overridepublic void run(){System.out.println("线程名:" + Thread.currentThread().getName());//发生异常int i = 1 / 0;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}
}

结果我们发现,我们尝试在main方法中对线程中抛出的异常进行捕获,但是毫无作用。

三、那么,JVM如何处理线程中抛出的异常的呢

查看Thread类的源码,我们可以看到有个dispatchUncaughtException方法,此方法就是用来处理线程中抛出的异常的。JVM会调用dispatchUncaughtException方法来寻找异常处理器(UncaughtExceptionHandler),处理异常。

    /*** Dispatch an uncaught exception to the handler. This method is* intended to be called only by the JVM.*///向handler分派未捕获的异常。该方法仅由JVM调用。private void dispatchUncaughtException(Throwable e) {getUncaughtExceptionHandler().uncaughtException(this, e);}/*** Returns the handler invoked when this thread abruptly terminates* due to an uncaught exception. If this thread has not had an* uncaught exception handler explicitly set then this thread's* <tt>ThreadGroup</tt> object is returned, unless this thread* has terminated, in which case <tt>null</tt> is returned.* @since 1.5* @return the uncaught exception handler for this thread*/// 获取用来处理未捕获异常的handler,如果没有设置则返回当前线程所属的ThreadGrouppublic UncaughtExceptionHandler getUncaughtExceptionHandler() {return uncaughtExceptionHandler != null ?uncaughtExceptionHandler : group;}

UncaughtExceptionHandler必须显示的设置,否则默认为null。若为null,则使用线程默认的handler,即该线程所属的ThreadGroup。ThreadGroup自身就是一个handler,查看ThreadGroup的源码就可以发现,ThreadGroup实现了Thread.UncaughtExceptionHandler接口,并实现了默认的处理方法。默认的未捕获异常处理器处理时,会调用 System.err 进行输出,也就是直接打印到控制台了。

public void uncaughtException(Thread t, Throwable e) {if (parent != null) {parent.uncaughtException(t, e);} else {Thread.UncaughtExceptionHandler ueh =Thread.getDefaultUncaughtExceptionHandler();if (ueh != null) {ueh.uncaughtException(t, e);} else if (!(e instanceof ThreadDeath)) {System.err.print("Exception in thread \""+ t.getName() + "\" ");e.printStackTrace(System.err);}}}

由此可知,最终JVM是调用未捕获的异常处理器的uncaughtException()方法来处理异常的,并且是直接打印到控制台。

四、如何自定义处理线程异常

如果我们要自己处理异常,该怎么办呢?通过前面的分析,我们已经知道了线程会使用默认的未捕获异常处理器来处理异常。自然我们可以想到,是否可以自定义未捕获异常处理器,覆盖掉默认的捕获异常处理器。实际上,Thead确实已经提供了一个setUncaughtExceptionHandler方法,我们只需要将自定义未捕获异常处理器作为参数传入进入就可以了。

接下来我们自定义处理线程异常

package com.joshua317;public class ThreadException {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.setUncaughtExceptionHandler();myThread.start();}
}class MyThread extends Thread {@Overridepublic void run(){System.out.println("线程名:" + Thread.currentThread().getName());//发生异常int i = 1 / 0;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}public void setUncaughtExceptionHandler(){this.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {@Overridepublic void uncaughtException(Thread t, Throwable e) {System.out.println("捕获线程抛出的异常:" + e.getMessage());}});}
}

五、线程池中自定义处理异常

要自定义处理异常,只需要为线程提供一个自定义的UncaughtExceptionHandler。而在线程池中,该如何批量的为所有线程设置UncaughtExceptionHandler呢?我们知道,线程池中的线程是由线程工厂创建的。我们可以跟踪ThreadPoolExecutor构造方法的源码,最终定位到DefaultThreadFactory类,该类中有个newThread()方法,这就是线程产生的源头了。

//ThreadPoolExecutor类中
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);}//Executors类中  
public static ThreadFactory defaultThreadFactory() {return new DefaultThreadFactory();}//DefaultThreadFactory类中
public Thread newThread(Runnable r) {Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);if (t.isDaemon())t.setDaemon(false);if (t.getPriority() != Thread.NORM_PRIORITY)t.setPriority(Thread.NORM_PRIORITY);return t;}

找到了线程创建的源头,我们就可以实现一个自己的线程工厂,并覆盖默认的newThread方法,为新创建的线程提供一个UncaughtExceptionHandler,即可达到我们的目的。由于DefaultThreadFactory是Executors类的内部类,我们不能直接继承该类,只能实现该工厂类的接口——ThreadFactory接口,来实现我们自己的线程工厂。

package com.joshua317;import java.util.concurrent.ThreadFactory;public class MyThreadFactory implements ThreadFactory {@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread();//自定义UncaughtExceptionHandlert.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());return t;}
}class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{@Overridepublic void uncaughtException(Thread t, Throwable e) {System.out.println("捕获线程抛出的异常:" + e.getMessage());}
}

本文为joshua317原创文章,转载请注明:转载自joshua317博客 多线程中如何进行异常处理? - joshua317的博客

http://www.lbrq.cn/news/1879813.html

相关文章:

  • 企业网站的开发背景/搜狗站长平台主动提交
  • angular2是做网站的还是手机的/自己手机怎么免费做网站
  • wordpress默认站点/网络营销专业就业方向
  • 成都网站建站公司/苏州seo排名优化课程
  • wordpress 电商主题/seo岗位
  • 西安网站建设seo/百度推广登录官网
  • 怎么看一个网站是不是外包做的/百度广告客服电话
  • 北京网站设计制作哪家好/百度关键词收录
  • 制作网站的方法/衡阳seo快速排名
  • 怎么搭建自己公司网站/zac博客seo
  • 文本文档做网站怎么加图片/社群营销的具体方法
  • 网站icon怎么做的/最近一周新闻大事摘抄
  • 深圳南山住房和建设局网站官网/网络营销课程有哪些
  • 网站开发包括几部分/百度免费推广怎么操作
  • 北京有哪些网站建设公司/深圳google推广
  • 计算机前端和后端/seo技术介绍
  • 即时设计网站/石家庄关键词优化报价
  • 网站建设服务哪家好/济南seo排名优化推广
  • 商务咨询网站源码/黑五类广告推广
  • ps怎么排版规划设计网站/鹤壁seo推广
  • wordpress文章 代码块/google 优化推广
  • 邢台市属于哪个省/杭州网站推广优化公司
  • 济南网站建设公司大全/泰安百度推广电话
  • 扶风网站建设/收录网站排名
  • 石家庄做网站公司哪家好/成都seo优化排名推广
  • 旅游网站有哪些/百度推广服务费一年多少钱
  • 丰台深圳网站建设公司/广州专业seo公司
  • 沂水县住房和建设局网站/网络整合营销4i原则
  • 电话销售怎么做 网站/一键生成app制作器
  • 专门做图标的网站/营销策划方案模板范文
  • AI Agent开发学习系列 - langchain之LCEL(1):LangChain LCEL链式编排与RAG增强实践
  • HTML进阶
  • Hadoop架构演进:从1.0到2.0的深度对比与优化解析
  • HashMap详解
  • 【第二章自定义功能菜单_MenuItemAttribute_顶部菜单栏(本章进度1/7)】
  • ethers.js-5–和solidity的关系