前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >警惕ThreadLocal和ThreadPoolExecutor同时使用

警惕ThreadLocal和ThreadPoolExecutor同时使用

作者头像
普通程序员
发布2019-10-23 11:46:47
2.4K1
发布2019-10-23 11:46:47
举报
文章被收录于专栏:普通程序员普通程序员

项目中有一个水平分库读写数据的场景,采用了Spring支持的分库策略AbstractRoutingDataSource,数据源名称采用了ThreadLocal来保存,具体执行读写库操作采用ThreadPoolExecutor线程池来做并发控制。Spring配置文件中配置有默认的数据源,代码中不显示调用分库代码研发人员认为会走默认数据源。然而,实际运行结果超出了研发人员的预期:不显示调用分库代码,实际读写的数据库不一定是默认数据源!

这到底是怎么回事呢(也许前面一段文字没看懂,但是不影响后边的内容)?

ThreadLocal会为每个线程保存一份成员变量的副本,而ThreadPoolExecutor是一些线程不断执行各种任务(线程复用)。比如,你让具有3个线程的ThreadPoolExecutor执行13个任务,那么有一个线程会执行5个任务,另外两个线程执行4个任务。那么,每个线程执行的这几个(5个或4个)任务,会共享ThreadLocal的数据备份。并不是每个任务有一个数据副本。

来段代码说明

TestNum类中定义sewNum这样一个ThreadLocal量,每个线程访问这个类时,都会有一个seqNum的副本。

定义一个任务,打印ThreadLocal变量值

在一个具有3个线程的线程池中,执行13个任务

输出结果,可以看到每个线程,都有一份ThreadLocal的数据备份。但是这些任务并没有独立的数据副本(同一线程执行的任务,共享同一个副本数据)

这就是文章开头提到的分库BUG产生的原因。程序员产生了每个任务都有一个数据副本的错觉。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 普通程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档