由DateFormat引起的线程安全问题
有一次在测试环境中有个插入重复主键的问题,代码如下
@Transactional public void lending(OrderExtend order) { Date date = DateUtil.getCountyTime(); ................................... // 更新限额金额 String nowDate = DateUtil.timeToString(date, DateUtil.DATE_FORMAT_23); OrderLimit limit = orderLimitMapper.selectLimitByDate(nowDate, order.getAppPackage()); if (limit == null) {// SystemOption record = new SystemOption(); record.setOptionGroup("dailyorderlimit"); record.setOptionKey(order.getAppPackage()); List<SystemOption> list = systemOptionMapper.selectBySelective(record); limit = new OrderLimit(); limit.setAppName(order.getAppName()); limit.setAppPackage(order.getAppPackage()); limit.setLimitTime(date); limit.setApplyNumber(1); limit.setApplyAmount(order.getLendingAmount()); limit.setUpdateTime(date); limit.setMaxNumber(Integer.valueOf(list.get(0).getOptionValue())); orderLimitMapper.insertSelective(limit); } else { limit.setLimitTime(date); limit.setUpdateTime(date); limit.setApplyAmount(order.getLendingAmount()); orderLimitMapper.updateOrderLimitAmount(limit); } } public class DateUtil {
public static SimpleDateFormat DATE_FORMAT_23 = new SimpleDateFormat("yyyy-MM-dd");
public static String timeToString(Date d, DateFormat dateFormat) { if (d == null) { return null; } return dateFormat.format(d); } }
原因是orderLimitMapper.selectLimitByDate找不到值,结果插入导致重复的唯一键。然后分析居然是sql里传入的时间不对,传入的时间是个莫名奇妙的日期,但这个时间是在方法内定义的一个局部变量啊,应该不是线程安全啊。结果我想错了,因为DATE_FORMAT_23是一个静态变量,在方法区的变量照样是在堆里的,同样会遇到线程安全的问题。网上一查果然SimpleDateFormat不是线程安全的
喜欢艺术的码农
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人