写在前面:这两天做了一个查询接口,由于查询条件和参数太多,采用了链式操作,链式操作的类是个spring service 的bean,执行查询的过程中需要缓存List HashMap 等线程不安全的对象,怎么办捏?
解决过程:
最终通过检索关键字“spring bean 线程安全”找到了答案:
http://www.cnblogs.com/doit8791/p/4093808.html
经过测试,ThreadLocal 是最高效的解决线程安全问题的方法,使用方法如下:
@Component
public class ProcessInstanceQueryImpl implements ProcessInstanceSampleQuery {
/**
这种不是线程安全的对象不要放在service的成员变量中
private Map<String, Object> filtrations = new HashMap<String, Object>();
private Map<String, JSONObject> boMap = new HashMap<String, JSONObject>();
private Map<String, BpBasicInfo> basicInfoMap = new HashMap<String, BpBasicInfo>();
private List<String> businessKeyList = new ArrayList<String>();**/
//创建一个ThreadLocal的类Context来缓存那些每次查询链需要用到的成员变量
private static ThreadLocal<Context> context = new ThreadLocal<Context>();
private static enum RelativeCode {
RELATIVE, RELATIVED, MERGE, MERGED, SPLIT, SPLITED
};
@Resource
private UniversalManager universalManager;
//Context类用来缓存那些每次查询链需要用到的成员变量
private static class Context {
private BpQuery<?, ?> query;
private List<String> boQuerys;
private String boFilterHql;
private String bpInfoHql;
private StringBuilder boHql;
private String orderHql;
private String sortType;
private String queryType;
private Context() {
boQuerys = new ArrayList<String>();
boFilterHql = "select new com.cayenne.bpm.workbench.model.BpBasicInfoAndBo(bpInfo1,bo) from ${boName} as bo ,BpBasicInfo as bpInfo1 where bo.id=bpInfo1.boId ";
bpInfoHql = "and bo.id in(select bpInfo.boId from BpBasicInfo as bpInfo where 1=1";
orderHql = "";
sortType = "";
queryType = "";
boHql = new StringBuilder(" ");
}
}
//每次调用该service进行链式查询时,先初始化查询链,创建一个Context线程安全对象
@Override
public ProcessInstanceSampleQuery initProcessInstanceSampleQuery() {
//set线程安全的查询对象
signal.set(new Context());
return this;
}
@Override
public ProcessInstanceSampleQuery queryTask(String processDefinitionKey) {
//获取线程安全对象,并赋值
signal.get().query = createCandiatesQuery(processDefinitionKey);
}
结论:
需要在同一个线程中调用的对象,
定义时,
ThreadLocal<Context> context = new ThreadLocal<Context>();
初始化时,
signal.set(new Context());
获取时,
signal.get();
(在未调用set方法之前,都是同一个线程之前set的signal值)
如果想要每次
signal.get();
获取的是初始化后的结果,那么定义时写成:
ThreadLocal<Context> context = new ThreadLocal<Context>(){
@Override
protected Context initialValue() {
return new Context();
}
};
-*-&-*-&-*-&-*-&-*-&-*-&-*-&-*-&-*后知后觉的分割线-&-*-&-*-&-*-&-*-&-*-&-*-&-*-&-*-&-*
今天解决别的问题,突然发现,这个Context就是俗称的上下文类,并且在Activiti,spring等源码中也看到了相关的应用,这东西专门用来处理线程安全问题的,哈哈,终于明白了
分享到:
相关推荐
当需要在线程中获取Spring注解的bean时,有几种常见的方法: 1. **ThreadLocal**:Spring提供了一种名为`ThreadLocalTargetSource`的特殊`TargetSource`实现,可以将bean实例绑定到当前线程。这样,每个线程都有其...
一个Spring框架的bean工具,可以在多线程环境下手动创建bean。使用时请注意在spring配置文件下加入<bean id="springBeanUtils" class="com.hujin.common.util.SpringBeanUtils"/>
在大数据采集项目中,这种灵活性非常有用,因为有时我们可能需要在非Spring管理的组件或线程中访问配置信息或依赖的Bean。确保正确初始化和管理`ApplicationContext`以及配置属性,就能在任何地方充分利用Spring的...
在Spring框架中,`@Bean`注解是一个关键的组件,用于声明一个方法将返回的对象作为Spring容器中的bean。在`@Bean`中定义`initMethod`属性,可以指定该bean初始化时需要调用的方法。当`initMethod`被设置为异步执行,...
在IT行业中,安全性和线程管理是任何应用开发的核心部分,尤其是在使用Spring和Ibatis这样的流行框架时。本文将深入探讨如何在Spring框架下结合Ibatis实现安全的线程处理,确保多用户并发访问时的数据一致性与系统...
在Spring Boot应用中,事务管理和多线程是两个非常关键的特性,特别是在处理复杂的业务逻辑时。本示例将深入探讨如何使用注解来实现事务控制以及如何在Spring Boot中运用多线程。 首先,让我们关注"注解事务"。在...
在实际项目中,我们还需要关注线程安全问题,比如同步机制(synchronized关键字、Lock接口)、线程间通信(wait、notify、Condition)以及并发工具类(ConcurrentHashMap、CountDownLatch、CyclicBarrier、Semaphore...
2. **线程安全**:当多个Job实例并行运行时,确保注入的Bean是线程安全的,或者对并发访问进行了适当的同步控制。 3. **Job实例复用**:Quartz允许Job实例的复用,因此要确保Job类的状态不会在不同调度之间互相干扰...
总结来说,Spring 中的单例模式虽然方便了对象管理,但如果不注意线程安全问题,可能会导致意料之外的结果。在设计类时,应该根据业务需求谨慎选择实例化策略,并且对于可变状态的单例类,应采取适当的同步措施或改...
在 Spring 框架中,多线程下注入 Bean 是一个常见的问题。本文将详细介绍 Spring 多线程下注入 Bean 问题,并提供两种解决方案。 问题描述 在多线程环境下,使用 Spring 框架时,可能会遇到 Bean 注入失败的问题。...
本文将深入探讨在Spring中如何利用多线程和动态任务来实现异步处理,并分享一些实践心得。 首先,我们要理解Spring的异步处理机制。Spring通过`@Async`注解实现了方法级别的异步执行。当一个带有`@Async`的方法被...
为了保证线程安全,开发者需要额外的同步机制,如使用`synchronized`关键字或Lock,但这会增加代码的复杂性。相比之下,"prototype"作用域的Bean每次请求都会创建新的实例,避免了线程安全问题,但代价是性能的降低...
在Spring框架中,Bean的线程安全性是一个常见的面试话题。首先,我们要明确Spring本身并不提供任何内置机制来确保Bean的线程安全。Spring容器只是一个管理Bean生命周期和依赖注入的工具,它并不负责处理线程安全问题...
4. **同步访问**:对于必须在Controller中保存的共享状态,可以使用`synchronized`关键字或者`Collections.synchronizedMap()`来确保线程安全。然而,这通常会导致性能下降,因为线程需要等待其他线程释放锁。 5. *...
需要注意的是,虽然`Singleton`作用域下的Bean在整个容器中是唯一的,但这并不意味着它是线程安全的。开发者需要确保Bean内部的状态管理符合多线程环境的要求。 #### 四、Prototype作用域 **Prototype**作用域下的...
在Spring框架中,Bean是核心概念,它是Java对象在Spring容器中的实例,通过XML或Java配置来定义。本文将深入探讨Spring项目中的Bean基础配置、别名配置以及作用范围配置。 首先,我们来理解Bean的基础配置。在...
在Web应用中,如果Bean被设计为单例,并且需要处理多个用户的请求,那么必须确保这些Bean是线程安全的。Spring提供了一些策略来确保Bean的安全性,如使用线程局部变量、同步方法或避免使用共享状态。 其次,最常见...
注意在并发环境中,必须确保HttpClient的线程安全,例如,避免在多个线程之间共享同一个HttpClient实例,而是为每个请求创建新的HttpClient,或者使用连接池来复用连接。 总的来说,HttpClient与Spring的结合使得在...