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

写在前面:这两天做了一个查询接口,由于查询条件和参数太多,采用了链式操作,链式操作的类是个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的类Single来缓冲那些每次查询链需要用到的成员变量
 private static ThreadLocal<Single> signal = new ThreadLocal<Single>();
 private static enum RelativeCode {
        RELATIVE, RELATIVED, MERGE, MERGED, SPLIT, SPLITED
    };

 @Resource
 private  UniversalManager universalManager;

//Single类用来缓冲那些每次查询链需要用到的成员变量
 private static class Single {
        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 Single() {
            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进行链式查询时,先初始化查询链,创建一个Single线程安全对象
    @Override
    public ProcessInstanceSampleQuery initProcessInstanceSampleQuery() { 
        //set线程安全的查询对象
        signal.set(new Single());
        return this;
    }
    @Override
    public ProcessInstanceSampleQuery queryTask(String processDefinitionKey) {
        //获取线程安全对象,并赋值
        signal.get().query = createCandiatesQuery(processDefinitionKey);
    }

结论:
需要在同一个线程中调用的对象,
定义时,ThreadLocal<Single> signal = new ThreadLocal<Single>();
初始化时,signal.set(new Single());
获取时,signal.get();(在未调用set方法之前,都是同一个线程之前set的signal值)
如果想要每次signal.get();获取的是初始化后的结果,那么定义时写成:ThreadLocal<Single> signal = new ThreadLocal<Single>(){
  @Override
        protected Single initialValue() {
            return new Single();
        }
};

你可能感兴趣的:(java,spring,bean)