广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >怎么解决异步任务所导致的问题
  • 685
分享到

怎么解决异步任务所导致的问题

2024-04-02 19:04:59 685人浏览 独家记忆
摘要

这篇文章主要介绍“怎么解决异步任务所导致的问题”,在日常操作中,相信很多人在怎么解决异步任务所导致的问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么解决异步任务所导致的

这篇文章主要介绍“怎么解决异步任务所导致的问题”,在日常操作中,相信很多人在怎么解决异步任务所导致的问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么解决异步任务所导致的问题”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

前言

先简单说下这段代码,就是使用一个异步线程执行一段业务逻辑,示例代码如下:

// 前置逻辑 ..... Thread thread=new Thread(new Runnable() {     @Override     public void run() {         try {            // 异步线程执行其他业务逻辑         } catch (Exception e) {            // 不进行任何代码处理         }     } }); thread.start();

凭着老程序员的经验,猜到可能是异步线程内发生了异常,导致异步线程退出,不再继续执行。而又因为上述代码「吃掉」了异常,这就导致我们从外部看起来这个工程跑着跑着就不动了,日志什么也没了。

于是改造了一下,打印出相关异常日志,最终定位问题,原来是小姐姐造的数据存在问题,从而引发 NPE 问题。

「不知道大家有没有碰到过上面的情况,使用线程异步执行相关逻辑,但是执行到一半突然就像卡主一般,不再继续往下执行。」

总结起来分为下面三种情况:

  • 异步任务长时间被阻塞

  • 异步任务发生异常

  • 异步任务异常被吃掉

异步任务长时间被阻塞

第一种,异步线程执行任务,这个任务需要通过网络调用其他远端服务。假设服务端响应的非常慢,而我们设置的网络超时时间又很长,这就会导致这个线程长时间被阻塞。

假设异步任务伪码如下:

ThreadPoolExecutor threadPool= ....; threadPool.execute(() -> { // 1.调用远端服务 Socket socket....; // 2.设置超时时间 socket.setSoTimeout(60*1000); // 3.读取服务端返回 socket.read(); });

上面程序中,如果服务端一直没有返回,那么异步线程将会一直被阻塞,直到超时。

这种情况其实还好,我们无非等待一段时间,就可以看到异步线程继续往下执行任务。

举一个极端的例子,假设上面的代码没有设置超时时间,而服务端一直没有返回响应,「此时异步线程就会被一直阻塞」。

除了上面网络读取阻塞的例子,常见情况还有

  • 执行了长时间休眠,比如 TimeUnit.MINUTES.sleep(60)

  • 内部发生了死

  • 等等

如果异步线程长时间被阻塞,而异步任务执行又比较频繁,那么线程池内可用线程将会被慢慢耗尽,此时后续任务就会被拒绝执行。

解决办法

其实非常简单,首先我们使用 jstack 命令 「dump」 一下当前 Java 应用的线程堆栈情况,然后根据线程池名字定位相关线程即可。

怎么解决异步任务所导致的问题

网上随便找了堆栈图

如果没有自定义线程池 ThreadFactory 参数,那查找定位被阻塞线程就比较麻烦了。

所以创建线程池建议自定义 ThreadFactory 参数,这对于后期排查问题非常有用。

异步任务异常未捕获

上面的情况,异步线程其实还活着,只是被阻塞没办法执行后续的逻辑。

那这一类情况呢,与上面不太一样,由于异步任务内部发生错误,抛出异常,而代码逻辑中又没有进行捕获处理,从而导致线程提前异常退出。

异常退出伪码如下:

// 1.创建执行的任务 Runnable runnable=new Runnable() {     @Override     public void run() {        // 执行前置逻辑         // 抛出异常         int i=100/0;        // 执行后置逻辑              } }; // 2.创建线程 Thread thread=new Thread(runnable); // 3.运行异步线程 thread.start(); // 其他业务逻辑

上述代码中,异步线程执行到除零逻辑,将会抛出异常,然后异步线程将会异常退出。

「异步线程内抛出的异常日志仅仅只会被打印到控制台,而不会被记录到日志文件中。」

所以正常的业务日志中是见不到线程异常的日志,这就给了我们一种假象,异步线程看起来还在执行任务,其实它已经挂了。

PS:上面的话可能不好理解,举个例子,如果你使用 idea 执行上面这段程序,异常日志将会被输出到 IDEA 下方控制台。

而如果我们在 linux 机器上执行这段程序,异常日志仅仅只会显示在当前终端窗口上,一旦关闭当前终端窗口,日志就没。了。

如果想要保存这种日志,我们需要将 stdout 重定向到日志文件中,比如执行以下命令:

-- 将 stdout 重定向输出到文件中 nohup java  xxxx > $STDOUT_FILE 2>&1 &

解决办法

第一种解决办法,其实很多读者已经想到了,异步线程内使用 try..catch 语句捕获所有异常即可。

「没错,就是这么简单。」

不过这里提一点,一般我们使用 try..catch仅仅只会捕获 Exception异常。

那么极端情况下,异步线程内如果抛出 Error,比如抛出了  java.lang.NoClassDefFoundError,此时是没法捕获,异步线程依旧会异常退出。

所以我们可以使用try..catch捕获 Throwable,这样及时发生 Error错误,也会被捕获。

不过个人觉得捕获Exception异常就够了,正常工程应用很少会发生 Error错误,所以我们只要了解有这个可能即可。

ps:之前同事上线一个应用,使用异步线程执行任务,每次执行到一半,都不再继续执行。

由于异步线程内使用try..catch捕获处理了 Exception异常,所以找了半天不知道什么问题。

最后,小黑哥排查 stdout 输出日志,才发现异步线程发生 Error错误。

这种解决本法需要我们主动去捕获异常,而下面第二种解决办法,设置线程异常处理方法。

一旦设置完成,如果异步线程内发生异常,线程退出之前将会调用异常处理方法。

我们拿 Thread 来讲,其设置方法如下:

Runnable runnable=new Runnable() {     @Override     public void run() {         int i=100/0;     } };  Thread thread=new Thread(runnable); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {     @Override     public void uncaughtException(Thread t, Throwable e) {         System.out.println(t.getName()+"发生异常"+e.getMessage());     } }); thread.start();

不过生产环境不建议直接使用 Thread,我们需要使用线程池代替。

线程池设置异常处理方法可以分为两种,如果我们使用 ThreadPoolExecutor#execute执行异步任务,那我们需要在自定义线程池的时候,使用  ThreadFactory 设置。

ThreadPoolExecutor threadPool =new ThreadPoolExecutor(         5,         10,         60,         TimeUnit.SECONDS,new ArrayBlockingQueue<>(100),       // 这里使用 Guava 的 ThreadFactoryBuilder 类,方便构造 ThreadFactory         new ThreadFactoryBuilder().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {             @Override             public void uncaughtException(Thread t, Throwable e) {                 // 处理异常             }         }).build()         );

如果你当前使用 ThreadPoolExecutor#submit执行异步任务,那就简单了,我们可以直接通过  Future#get获取到线程内抛出的异常。

Future<?> future = threadPool.submit(new Callable<Object>() {     @Override     public Object call() throws Exception {         return "小黑十一点半";     } });  try {     future.get(); } catch (InterruptedException e) {     e.printStackTrace(); } catch (ExecutionException e) {     // 线程内抛出异常将会被封装在 ExecutionException 内 }

异步任务异常被吃掉

好了,终于到最后一种情况了,小黑哥这次碰到就是这种??。

这种情况具体来说就是异步线程内使用  try..catch 语句捕获了所有异常,但是没有在 catch语句中进行任何代码处理。

Thread thread=new Thread(new Runnable() {     @Override     public void run() {         try {             int i=100/0;         } catch (Exception e) {            // 不进行任何代码处理         }     } }); thread.start();

如上述代码所示,catch语句中没有进行任何代码处理。即使异步线程内真发生了异常,也不会有任何提示,这个异常就像被吃掉一般。

到此,关于“怎么解决异步任务所导致的问题”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 怎么解决异步任务所导致的问题

本文链接: https://www.lsjlt.com/news/83974.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么解决异步任务所导致的问题
    这篇文章主要介绍“怎么解决异步任务所导致的问题”,在日常操作中,相信很多人在怎么解决异步任务所导致的问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么解决异步任务所导致的...
    99+
    2022-10-19
  • golang异步任务队列问题怎么解决
    在Go语言中,可以使用goroutine和channel来解决异步任务队列的问题。下面是一个简单的示例代码,演示了如何使用gorou...
    99+
    2023-10-20
    golang
  • ADO Error导致的问题怎么解决
    这篇文章主要介绍“ADO Error导致的问题怎么解决”,在日常操作中,相信很多人在ADO Error导致的问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”ADO Error导致的问题怎么解决”的疑...
    99+
    2023-06-17
  • hover导致位置错乱的问题怎么解决
    这篇文章主要介绍了hover导致位置错乱的问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇hover导致位置错乱的问题怎么解决文章都会有所收获,下面我们一起来看看吧。...
    99+
    2022-10-19
  • 怎么解决Mysql tools中orztop导致的错误问题
    这篇文章主要介绍“怎么解决Mysql tools中orztop导致的错误问题”,在日常操作中,相信很多人在怎么解决Mysql tools中orztop导致的错误问题问题上存在疑惑,小编查阅了各式资料,整理出...
    99+
    2022-10-19
  • react usestate异步问题怎么解决
    在React中,useState钩子是同步的,它不会自动处理异步操作。因此,当遇到需要在useState之后执行异步操作的情况时,可...
    99+
    2023-10-07
    react
  • 如何解决多个Tab页点击切换功能所导致的问题
    本篇内容主要讲解“如何解决多个Tab页点击切换功能所导致的问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何解决多个Tab页点击切换功能所导致的问题”吧!大...
    99+
    2022-10-19
  • mongo的tickets被耗尽导致卡顿问题怎么解决
    这篇文章主要介绍了mongo的tickets被耗尽导致卡顿问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇mongo的tickets被耗尽导致卡顿问题怎么解决文章都会有所收获,下面我们一起来看看吧。t...
    99+
    2023-07-05
  • react异步渲染问题怎么解决
    在React中,可以使用异步渲染来优化性能并提升用户体验。有几种方式可以解决React异步渲染问题:1. 使用React.lazy和...
    99+
    2023-08-19
    react
  • 如何使用Promise解决多个异步Ajax请求导致的代码嵌套问题
    这篇文章将为大家详细讲解有关如何使用Promise解决多个异步Ajax请求导致的代码嵌套问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。问题前端小同学在做页面的时候,犯...
    99+
    2022-10-19
  • MYSQL大小写不敏感导致用户登录异常问题怎么解决
    这篇文章主要介绍“MYSQL大小写不敏感导致用户登录异常问题怎么解决”,在日常操作中,相信很多人在MYSQL大小写不敏感导致用户登录异常问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MYSQL大小...
    99+
    2023-07-06
  • jQuery Ajax async=>false异步改为同步时如何解决导致浏览器假死的问题
    这篇文章主要介绍jQuery Ajax async=>false异步改为同步时如何解决导致浏览器假死的问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!大概代码如下: &nbs...
    99+
    2022-10-19
  • nginx上传请求体太大导致的问题怎么解决
    这篇文章主要讲解了“nginx上传请求体太大导致的问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nginx上传请求体太大导致的问题怎么解决”吧!1.原因GitLab  ...
    99+
    2023-06-04
  • quartz任务阻塞问题怎么解决
    解决Quartz任务阻塞问题的方法有以下几种:1. 增加线程池大小:默认情况下,Quartz使用一个线程执行任务。如果任务较多或者任...
    99+
    2023-09-18
    quartz
  • Vue的异步渲染axios问题怎么解决
    本文小编为大家详细介绍“Vue的异步渲染axios问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue的异步渲染axios问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Vue异步渲染ax...
    99+
    2023-07-05
  • 怎么使用JS promise解决异步问题
    这篇“怎么使用JS promise解决异步问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用JS ...
    99+
    2023-07-05
  • 如何解决Go语言中的并发任务的任务失败重试和异步任务处理问题?
    如何解决Go语言中的并发任务的任务失败重试和异步任务处理问题?在Go语言中,并发是一种非常常见的处理方式,可以提高程序的性能和响应速度。然而,并发任务在执行过程中可能会遇到一些错误和异常情况,这就需要处理任务失败重试和异步任务。本文将分享一...
    99+
    2023-10-22
    并发任务 (Concurrent Tasks) 任务失败重试 (Task retry) 异步任务处理 (Asynchro
  • Android 异步获取网络图片并处理导致内存溢出问题解决方法
    测试环境为Adnroid 2.1以上。 1.AndroidManifest.xml 权限配置: 添加互联网访问权限: 代码如下: <uses-permission an...
    99+
    2022-06-06
    网络图 方法 图片 内存溢出 异步 Android
  • Spring处理@Async导致的循环依赖失败问题怎么解决
    本文小编为大家详细介绍“Spring处理@Async导致的循环依赖失败问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring处理@Async导致的循环依赖失败问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入...
    99+
    2023-07-02
  • 怎么解决Win10更改DPI设置导致字体模糊的问题
    这篇文章主要介绍“怎么解决Win10更改DPI设置导致字体模糊的问题”,在日常操作中,相信很多人在怎么解决Win10更改DPI设置导致字体模糊的问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么解决Win...
    99+
    2023-06-07
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作