系统中使用到了多线程,并且使用了自定义的事务管理,使用自定义事务的原因是因为一次交易会涉及到多个表的操作,但是这个操作不在同一个方法中,并且不是所有的表都需要回滚,所以就考虑了一下这个笨方法;该事务的实现方式是将表名、操作的字段名、字段值都放入的ArrayList中,有需要回滚的就放入到ArrayList中,最后最外层捕获异常的时候,将其中的ArrayList循环生成删除SQL语句,并执行。
但是这其中遇到了问题,就是多个线程相当于共享了这个变量,如第一次交易失败了,应该删除两个表的数据,就该生成两条删除语句,但是如果第二次失败了就不再是生成两条了,就是四条,第三次失败就是六条...
我的ThreadLocal的实现方式:
/**
 * insertActions用于存放字符串数组,该字符串数组包括"表名、字段名S(S表示可以多个字段,以逗号分开,其它相同)、字段值S、字段类型S(只分两种:String及Number)":
 * String[] action={"table1","field1","valu1","String"};//单字段的情况
 * 或
 * String[] action={"table1","field1,field2","valu1,value2","String,Number"};//多字段及值用逗号分开
 * 代表意义分别为:
 * action[0]:表名
 * action[1]:字段名称S
 * action[2]:字段的值S
 * action[3]:字段的类型S(String及Number)
 * 将其存放于ArrayList中,取出的时候,以上示例分别生成SQL语句:
 * delete table1 where field1='value1'
 * delete table1 where field1='value1' and field2=value2
 */
private static ArrayList insertActions;
private static ThreadLocal localInsertActions = new ThreadLocal(){
public void set(Object action){
if(insertActions==null){
insertActions=new ArrayList();
}
insertActions.add(action);
}
public Object get(){
return insertActions;
}
};
也即此时的insertActions不是每个线程单独使用本身的,而是线程使用了共享的insertActions,这个问题出在什么地方?

解决方案 »

  1.   

    ThreadLocal 有个关键的问题,那就是你怎么确定下一次运行的还是这个Thread.
    所以我一般都是在ThreadLocal里面保存一个Map,
    然后在线程开始是,设置一个ThreadLocal的key,然后因为每次ThreadLocal的key不同,则能从map里拿到准确的内容了。
      

  2.   

    to java2000_net:
      对于你说的,我有点明白,但是不是很明白,如果能够给一个简单的示例参考下,那更加感谢
      
      

  3.   

    现在想到一种解决方式,但是不知道是否行得通:
      因为线程池的存在,使每次启动的线程并不一定是最新的,因而采用ThreadLocal并不能够达到我们想要的一个连接单独使用ThreadLocal中所存放的内容的效果;而此时相当于是多次相同线程连接共用了一个ThreadLocal中的变量。
      我想:同一个线程,只会有一个用户在使用,也就是说一个线程在使用中,线程池不会将其分配置给其它的连接,如果我能够使用当前的的线程,那说明即使不是一个新的线程,也肯定是被释放了的线程;那么我可以在每次启动线程过后,不用去管它是否一个新的线程,我可以将ThreadLocal中的数据进行重新初使化,因为我不需要使用前面连接调用该线程产生的遗留数据,这样在线程结束的时候,获取的数据就完全是当前线程需要的数据。
      但是我不知道这种想法对不对?还请大家给电意见,因为从我个人的角度去看这样做是合理的
      

  4.   

    ThreadLocal 不要和静态成员一起用,而且 ThreadLocal 不是这么用的。