ThreadLocal的使用
作者BLOG:http://blog.youkuaiyun.com/fenglibing
由于项目中的需要,采用了ThreadLocal来记录当前线程的变量,但是因为了解的不是很清楚,曾经使用了两种错误的方式,导致了都达不到预期的效果,现在我把操作中用过的两种错误方式都记录下来,并附以正确的使用方式。
使用背景介绍:用于自定义事务的实现,即一个交易中会涉及到多个表的插入操作,但是并不是所有的表都要求回滚,部分表要求在交易失败的情况数据也不回滚,因而就不能用于统一的事务控制当中,于是考虑采用自定义事务。实现的方式是采用ThreadLocal记录当前需要回滚的交易操作,因为每个交易都需要独立的操作,然后在发生异常的时候,从ThreadLocal中去获取需要回滚的数据进行操作。
错误使用一:
public class TransactionMgmt { /*用于保留数据的ArrayList*/ private List 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; } }; /*新增需要回滚的操作*/ public static void newInsertDBAction(String[] action){ localInsertActions.set(action); } //...... }
|
错误说明:
每次在其它类中调用TransactionMgmt.newInsertDBAction(String[])的时候,insertActions记录只会有最后一条记录,因为每次这个类都是被重新初使化,因为它不是静态变量。
错误使用二:
将上一个版本的绿色部分,声明为静态的:
private static List insertActions; |
当前错误是在原来的错误基础之上的改进版本,在单线程的情况之下,如果用户在当前线程结束的时候再清理一下List,永远不会出错,并且可以达到用户的要求,因为现在在其它类中调用TransactionMgmt.newInsertDBAction(String[])的时候,插入的数据可以和原来的数据一起被放到List insertActions中了。但问题就是当前应用不是放在单线程中使用的,如果是单线程中使用就不用采用ThreadLocal来降隔离了。
ThreadLocal的正确使用:
public class TransactionMgmt { /*用于保留数据的ThreadLocal*/ private static ThreadLocal localInsertActions = new ThreadLocal(); /*新增需要回滚的操作*/ public static void newInsertDBAction(String[] action){ List insertActions=(List)localInsertActions.get(); if(insertActions==null){ insertActions=new ArrayList(); } insertActions.add(action); } //...... }
|
本文出自:冯立彬的博客