背景

在实现一个springboot日志记录的aop方法
但是为了防止日志记录的时候占用太多时间影响数据返回,所以采取了多线程记录日志的方法。

我的程序中有个定时任务,每个十分钟把redis中的数据取出来存到mysql中用来持久化,

个人背景(我只是对于多线程有过学习,但是从来没有亲自上手使用过多线程在业务代码上,对于多线程的理解十分片面)


我担心程序在读取完并存取的过程中有新的日志存到redis中会被误删,所以进行了简易的加锁操作

代码如下

public void saveLogFromRedisToMysql() {if(redisUtils.hasKey(MhtLogKey)){if(redisUtils.hasKey(logLockKey)){//有锁加一redisUtils.incr(logLockKey,1);}else{//没锁创造锁redisUtils.set(logLockKey,1);}List<Object> logs = redisUtils.lGet(MhtLogKey,0,-1);List<AdminLog> adminLogs = new ArrayList<>();for(Object object:logs){AdminLog adminLog = (AdminLog) object;adminLogs.add(adminLog);}boolean flag = adminLogDao.batchSaveLogs(adminLogs);if(flag){redisUtils.del(MhtLogKey);}//释放锁redisUtils.decr(logLockKey,1);}}

然后在添加日志到redis中的代码中添加一个判断即可

public void pushMhtLogList(AdminLog adminLog) {while (true){//如果有锁就循环if(redisUtils.hasKey(logLockKey) && (redisUtils.get(logLockKey)).equals(1)){System.out.println("存入log等待释放锁中");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}else{break;}}redisUtils.lPush(MhtLogKey,adminLog);}

问题

这时候就有问题了,我时使用的@Async来实现多线程

 @Async("asyncServiceExecutor")void saveLoginLog(String username, HttpServletRequest request, Long beginTime) {****省去细节代码***redisService.pushMhtLogList(adminLog);}

我理所应当的认为这个函数是不在主线程运行的,那么他调用的redisService.pushMhtLogList(adminLog);
应该也是在另一个线程中运行的,不会影响主线程的运行结果

但是事与愿违

成功的让我的主线程无法返回结果

解决方法

经过几次试错之后
我在
redisService.pushMhtLogList
上加上了
@Async(“asyncServiceExecutor”)
就成功运行了

问题分析

根据我浅显的多线程知识分析,我认为
可能原因是
首先redisService.pushMhtLogList虽然实在子线程中被调用,但是自身不是一个多线程程序,因此在redisService.pushMhtLogList中使用Thread.sleep方法,导致了Thread指向的是主线程,因此主线程等待

不过又感觉不怎么对
最蛋疼的事我发现idea还不方便调试多线程(或许说根本调不了,因为我试了下调不了,百度也没搜索到正确的调试姿势,后来用的土办法log输出来调试的)

应该花点时间去研究一下@Async具体的实现原理,为啥在有@Async的函数中调用另一个函数会影响主线程。

效果展示

去请求

成功请求到数据

但是存log线程还卡着

记一次子线程Thread.sleep影响主线程的坑相关推荐

  1. java 主线程_Java中的主线程 - Break易站

    Java 多线程 Java为多线程编程提供内置支持.多线程程序包含两个或多个可以并发运行的部分.这样的程序的每个部分称为线程,每个线程定义一个单独的执行路径. Java中的主线程 当Java程序启动时 ...

  2. java 子线程退出_java – 在子线程完成执行之前主线程将退出吗?

    我读了2篇文章 在上面的文章中,在"线程终止"段中,它在Red中声明"如果父线程终止,它的所有子线程也会终止". 在上面的文章中,该页面的最后一行指出" ...

  3. Unity C# 子线程Action发送到主线程执行

    今天去面试..面试官竟然说子线程的Action不能发送到主线程执行... ...废话不说上干货 using System.Collections; using System.Collections.G ...

  4. 多线程遇到的问题:(2)子线程未运行完 主线程结束了

    问题: 用@Test测试多线程接口时,启动服务抛出异常: Singleton bean creation not allowed while singletons of this factory ar ...

  5. pthread线程传递数据回主线程_操作系统4:线程(1)

    接下来讨论下线程.进程和线程是一个很有趣的话题,进程和线程的区别到底是什么?一些书上讲线程是"轻量级进程",从而可以节省切换开销.但是线程到底是怎么样成为轻量级进程的呢? 可以设想 ...

  6. 每个java程序都至少有一个线程给主线程,java程序在主线程中判断各个子线程状态的操作,该如何解决...

    java程序在主线程中判断各个子线程状态的操作 每个子线程在队列为空时会wait等待其他线程添加新url到队列,到最后所有子线程都取不到url时也会都wait住,要在主线程中判断如果所有的子线程都是w ...

  7. Qt与OpenCV编程:在子线程打开摄像头用主线程显示

    前言 1.在做图像处理开发中,比例做目标跟踪识别的时候,用OpenCV一直在处理摄像头传入的数据,有时候会出现界面卡死或者未响应的状态,这是因为事件循环一直等待处理函数的返回而导致阻塞事件循环,这样一 ...

  8. Android中Handler消息传递机制应用之子线程不允许操作主线程的组件

    场景 进程 一个Android应用就是一个一个进程,每个应用在各自的进程中运行. 线程 比进程更小的独立运行的基本单位,一个进程可以包含多个线程. 要求 一个TextView和一个Button,点击B ...

  9. java 设置主线程_Java线程编程中的主线程讲解

    当Java程序启动时,一个线程立刻运行,该线程通常叫做程序的主线程(main thread),因为它是程序开始时就执行的.主线程的重要性体现在两方面: 它是产生其他子线程的线程: 通常它必须最后完成执 ...

最新文章

  1. 前端模块化--这是我看过讲得比较好的东东
  2. android服务的说法错误的是,下面关于Android开发描述有误的一项是()。
  3. ora-00054:resource busy and acquire with nowait specified解决方法
  4. html文字置顶标签,HTML的marquee标签怎么用?
  5. 即将放弃python的app_python放弃之 模块和包
  6. 中断处理程序与中断服务例程
  7. 动态路由协议_动态路由协议的类别
  8. Visual C# 诠释常用排序算法
  9. php中提取现在的时间函数,php中时间函数date及常用的时间计算
  10. Android报加密错误,在android中解密使用aes/gcm/nopadding加密的消息时出错
  11. apache + subversion + Windows认证
  12. mysql 触发器存储过程的区别_MySQL触发器、存储过程实现
  13. Java开发帮助文档
  14. 新浪微博热门话题(字符串处理)
  15. Spark处理数据倾斜问题
  16. linux 子接口 非vlan,VLAN之间通过子接口通信配置示例
  17. AKA传奇和亚嵌那些事
  18. web前端技术社区分享
  19. 计算机网络实验一:验证性实验
  20. Java 老矣,尚能饭否?

热门文章

  1. 初学者学习 - Unity中的热更新 - Lua和C#通信
  2. 新手如何对文件进行简单的上传
  3. 口碑最好的国产蓝牙耳机,2021国产最好用的蓝牙耳机
  4. 匿名飞控码STM32版代码整理之Ano_AttCtrl.c
  5. 用mg格式制作产品动画有什么优势?
  6. HTML5期末大作业:在线电影网站设计——我不是药神电影介绍(4页) HTML+CSS+JavaScript 大二实训大作业HTML源码
  7. 生物信息百Jia软件(28):canu
  8. 蛙蛙推荐:蛙蛙浏览器
  9. ElasticSeach 监控之cerebro
  10. 长芯微LCM1118 16 位模数转换器 P2P替代ADS1118