在项目中,发现Spring的定时任务中用ThreadLocal来保存上下文信息,且上下文信息中有一个属性在后面入库时是做为主键值。总觉得这里应该有问题,因为没有去看过Spring的定时任务的具体实现,也不知定时任务用没用线程池以及如何使用的,但如何用了线程池(且我觉得从性能和常理推测来看应该是要用的),用ThreadLocal保存上下文信息,并在后续使用(且使用完没有做remove),那么后面就一定会出现主键冲突呀。
为了偷懒,也为了尽快验证我的推断,写了一个很简单的测试代码如下。
为了偷懒,也为了尽快验证我的推断,写了一个很简单的测试代码如下。
Context.java
package com.bijian.study.dto; public class Context { private int seqNo; public int getSeqNo() { return seqNo; } public void setSeqNo(int seqNo) { this.seqNo = seqNo; } }
HelloService.java
package com.bijian.study.service; public interface HelloService { public String processService(String name) throws Exception; public String processService() throws Exception; }
HelloServiceImpl.java
package com.bijian.study.service.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.bijian.study.dto.Context; import com.bijian.study.service.HelloService; import com.bijian.study.util.ContextThreadLocal; @Service("helloService") public class HelloServiceImpl implements HelloService { private static Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class); private static int count; @Override public String processService(String name) throws Exception { logger.info("HelloService processService name:" + name); return "Hello " + name; } @Override public String processService() throws Exception { Context context = ContextThreadLocal.get(); if(context == null) { count++; context = new Context(); context.setSeqNo(count); ContextThreadLocal.set(context); } logger.info("HelloService processService seqNo:" + context.getSeqNo()); return "Hello " + context.getSeqNo(); } }
ContextThreadLocal.java
package com.bijian.study.util; import com.bijian.study.dto.Context; public class ContextThreadLocal { public static final ThreadLocal<Context> userContextThreadLocal = new ThreadLocal<Context>(); public static void set(Context userContext) { userContextThreadLocal.set(userContext); } public static void unset() { userContextThreadLocal.remove(); } public static Context get() { return userContextThreadLocal.get(); } }
springMVC-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd"> <context:component-scan base-package="com.bijian.study"></context:component-scan> <context:annotation-config /> <mvc:annotation-driven></mvc:annotation-driven> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/views" /> <property name="suffix" value=".jsp" /> </bean> <task:scheduled-tasks> <task:scheduled ref="helloService" method="processService" initial-delay="5000" fixed-delay="1"/> </task:scheduled-tasks> </beans>
运行结果:
从运行结果来看,Spring定时任务肯定用到了线程,且在上面这种运用场景是肯定会出现主键冲突。当然,这里的解决办法也很简单,即在使用完ThreadLocal中的上下文信息后,做remove的清理动作。
相关推荐
NULL 博文链接:https://yizhenn.iteye.com/blog/2293339
NULL 博文链接:https://xxxxxfsadf.iteye.com/blog/518275
主要介绍了详解Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
javaee开发常见的模式有MVC模式,在C层中常常会再次分层,如:servlet(web层)、service(业务逻辑层)、dao(数据访问层),其中service和dao最容易混在一起,如转...所以,使用ThreadLocal可以解决这样的分层问题。
Java中ThreadLocal的设计与使用.doc
详解java底层实现原理,ThreadLocal底层实现的数据结构,为什么不会导致内存泄露
NULL 博文链接:https://justsee.iteye.com/blog/791919
ThreadLocal入门教程。 讲解了线程安全和ThreadLocal的使用的基本知识。
使用c3p0数据源,进行转账操作的小型简单练习;使用ThreadLocal控制事务中的connection唯一,实现mvc三层结构互不干扰。
ThreadLocal应用示例及理解,这个写了相关的示例,可以参考一下。
通向架构师的道路(第七天)之漫谈使用ThreadLocal改进你的层次的划分
ThreadLocal
6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来...
在我们日常 Web 开发中难免遇到需要把一个参数层层的传递到最内层,然后中间层根本不需要使用这个参数,或者是仅仅在特定的工具类中使用,这样我们完全没有必要在每一个方法里面都传递这样一个 通用的参数。...
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...
NULL 博文链接:https://qixiaopeng.iteye.com/blog/551764