当前位置:首页 > IT科技

使用ThreadLocal差点让我怀疑自己见鬼了

前言

最近使用ThreadLocal出现了一个生产问题

一大清早就接到业务人员的使用电话,说系统登录进去后总是点让莫名其妙的报错,而且有点随机...昏沉的怀疑脑袋瞬间清醒了,我问具体是自己哪个模块报错,是见鬼不是操作了哪些特定的功能才报错,得到的使用回答是否定的,任何功能操作都随机报错?点让?,也就是怀疑有时候报错,有时候不报错。自己

一时间有点懵逼了,见鬼脑海里不断回忆这段时间是使用不是上了什么新版本,不对啊,点让最近也没有什么大版本啊,怀疑都是自己一些小改,不可能会影响到所有业务模块啊。见鬼

赶忙起床去公司~

到公司后赶忙去机房,查看后台日志,发现报的亿华云是空指针异常,接着继续定位代码,发现是这段代码是从链路日志模块报出来的,仔细看了下代码,发现报错是从链路日志那块报出来的,这块代码看起来也没啥问题,而且这个模块都投产好几个月了,从来都没有发生过类似的报错,跟了下代码,是从ThreadLocal中取值,第一反应是链路日志又问题,先不管了,业务催的紧,先把应用重启了。

说来也奇怪,重启后应用竟然没有再出现报错了,真的绝了,这下我更加好奇了,在开发环境进行debug,那块代码逻辑的伪代码如下

// 伪代码 1、高防服务器ThreadLocal的初始化 2、ThreadLocal threadlocal = new ThreadLocal(); 3、if(threadlocal.get() == null) threadlocal.set(XX) 4、....相关业务代码 5、threadlocal.get() 获取链路日志相关信息进行相关的处理 6、threadlocal.remove() 

咋一看,没啥问题,然而由于异常的信息导致第4步出现了异常,catch住了但是没有在finally里操作threadlocal.remove(),又因为第3步的判空对该线程无效了(这个线程已经被设置值了),从而该线程被污染了,

也就是每次用到这个被污染的线程就会报错,生产的随机报错就是这么来的,话不多说修bug。至此问题也解决了。

吸取教训:使用ThreadLocal时一定要记得考虑清楚场景,把各种情况都考虑全。

下面是对ThreadLocal的一些操作

没有进行remove操作

static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();     // 没有进行remove操作的ThreadLocal的表现     public static void main(String[] args) throws InterruptedException {          // 创建一个线程池         ExecutorService pool = Executors.newFixedThreadPool(2);         for (int i = 0; i <= 5; i++) {              final int count = i;             pool.execute(()->{                  Integer integer = threadLocal.get();                 System.out.println("云服务器提供商

分享到:

滇ICP备2023006006号-16