皮皮网

【拐点战法指标源码】【substring 源码】【mvvm源码】asynctask源码解析

来源:摄影博客源码 时间:2024-12-23 21:29:16

1.面试官问:SpringBoot中@Async默认线程池导致OOM如何解决?
2.JobIntentService源码解析

asynctask源码解析

面试官问:SpringBoot中@Async默认线程池导致OOM如何解决?

       面临问题

       在进行项目测试时,码解我们遇到了内存溢出(OOM)问题,码解具体日志显示为“unable to create new native thread”。码解该项目使用SpringBoot架构,码解我们通过Jstack工具分析,码解发现大量线程处于可运行状态,码解拐点战法指标源码表明线程创建量过大。码解

       问题解析

       内存溢出主要有三种类型:第一,码解PermGen space,码解通常因程序中加载大量JAR或Class文件引起;第二,码解Java heap space,码解由程序创建对象过多导致;第三,码解无法创建新本地线程,码解这可能因创建线程数量过多,码解导致内存消耗过大。码解

       初步分析

       根据日志分析,我们怀疑是线程创建过多导致的问题。通过将应用线程信息打印到文件,发现大量线程处于可运行状态,这进一步确认了线程创建过多的假设。

       代码探究

       问题出在日志写库服务的substring 源码`writeLog`方法上,该方法使用了`@Async`注解,实现异步写入逻辑。但服务并未自定义异步配置,而是使用了Spring默认的`SimpleAsyncTaskExecutor`线程池,该配置默认为每个任务创建一个新线程,这在高并发压测环境下,可能导致线程数量激增,从而导致内存溢出。

       深入了解

       `SimpleAsyncTaskExecutor`线程池具备限流机制,通过`concurrencyLimit`属性控制。mvvm源码默认情况下,此属性值为-1,即不开启限流,导致在高并发情况下持续创建线程。源码分析揭示了限流机制实现,即当线程数超过`concurrencyLimit`时,当前线程会进入等待状态,直至线程数减至允许范围。

       实践验证

       我们通过模拟测试验证了此机制。在未开启限流的asterisknow源码情况下,启动个线程调用异步方法,使用Java VisualVM监控工具观察到线程数迅速增长,直至达到系统限制。开启限流后,线程数得到了有效控制,但这也引入了执行效率的降低,出现了主线程等待和线程竞争的情况。这种限流机制适用于任务处理速度较快的场景,对于处理时间较长的应用并不适用。

       最终解决方案

       为解决线程创建过多导致的源码替换内存溢出问题,我们采取了以下策略:

       1. 自定义线程池,利用`LinkedBlockingQueue`阻塞队列限制线程池的最大线程数。

       2. 定义拒绝策略,当任务队列满时,拒绝处理新任务并记录日志。

       通过这些改进,我们成功解决了内存溢出问题,同时确保了应用的稳定性和响应效率。

JobIntentService源码解析

       Android 8.0引入了更严格的系统资源管控,包括后台限制规则。

       在Android 8.0中,禁止应用在后台运行时创建Service。

       若应用在后台运行,将会收到错误提示。

       JobIntentService是Android 8.0中新增的类,继承自Service。

       该类用于执行加入队列的任务。对于Android 8.0及以上系统,JobIntentService任务将通过JobScheduler.enqueue执行,而8.0以下系统则继续使用Context.startService。

       JobIntentService使用便捷,只需调用YourService.enqueueWork(context, new Intent())方法。

       相较于JobService,JobIntentService简化了操作,开发者无需关注其生命周期,避免了在后台运行时创建Service导致的crash问题,且通过静态方法即可启动。

       源码解析如下:首先记录几个关键变量的含义。

       在Android 8.0以上的系统中,执行流程如下。

       work的具体逻辑处理在何处?

       通过JobService的工作原理,查找onStartJob方法。

       最终,处理work的逻辑会流转至AsyncTask中,通过protected abstract void onHandleWork(@NonNull Intent intent)方法实现。

       子类需实现jobIntentService处理work,使用线程池的AsyncTask执行,无需考虑主线程阻塞问题。

       针对Android 8.0以下系统,流程如下:回到onStartCommand方法。

       同样,最终会流转至Asynctask任务执行onHandleWork。