如何保证spring bean中的线程安全

写在前面:这两天做了一个查询接口,由于查询条件和参数太多,采用了链式操作,链式操作的类是个spring service 的bean,执行查询的过程中需要缓存List HashMap 等线程不安全的对象,怎么办捏?
解决过程:
最终通过检索关键字“spring bean 线程安全”找到了答案:
[url]http://www.cnblogs.com/doit8791/p/4093808.html[/url]
经过测试,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等源码中也看到了相关的应用,这东西专门用来处理线程安全问题的,哈哈,终于明白了
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值