1.首先从类的成员变量有3个int类型的变量。其中threadLocalHashCode是类的实例变量,nextHashCode表示了下一个ThreadLocal实例的threadLocalHashCode的值,而HASH_INCREMENT是一个常量,表示每次threadLocalHashCode的增量。 threadLocalHashCode调用了nextHashCode()这个方法。这个方法的目的是将下一个hashCode的值赋值给了threadLocalHashCode,然后nextHashCode进行自增。 类的实例变量会在类每次实例化的时候初始化,所以每次实例化ThreadLocal的时候,它的threadLocalHashCode都会自增。 ThreadLocal是作为一个工具拿来给不同的对象来使用,为了区分不同的ThreadLocal的实例,所以需要定义threadLocalHashCode来区别不同的ThreadLocal实例。 2.在上面代码中,我们可以看到有一个ThreadLocalMap的类,这个类是ThreadLocal的内部类,受篇幅限制,并没有截图出来。这个内部类的实例却在Thread类中定义。 从上可以看到,每一个线程的实例的都有自己的成员变量threadLocals,也就是说是threadLocals这个对象依赖于每个线程存在。当调用set方法时,如果当前线程的threadLocals不为空,就把当前ThreadLocal实例做为key,要保持的对象做为值,设置到当前线程的ThreadLocalMap中;如果没有threadLocals,就创建并且设置。调用get方法的时候,从当前ThreadLocal对象和当前线程,取得对应的缓存对象。 ThreadLocal类通过操作每一个线程特有的ThreadLocalMap对象,从而实现了变量访问在不同线程中的隔离。因为每个线程的变量都是自己特有的,完全不会有并发错误。在JDK1.5之后,放在ThreadLocal中的对象,都是泛型,这样可以避免使用Object类型的强制类型转化。 ThreadLocal在Hibernate中的使用 以下为Hibernate中使用ThreadLocal的范例,我们可以学习一下 public class HibernateUtil { private static Log log = LogFactory.getLog(HibernateUtil.class); //定义SessionFactory private static final SessionFactory sessionFactory; static { try { // 通过默认配置文件Hibernate.cfg.xml创建SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { log.error("初始化SessionFactory失败!", ex); throw new ExceptionInInitializerError(ex); } } //创建线程局部变量session,用来保存Hibernate的Session public static final ThreadLocal session = new ThreadLocal(); //获取当前线程中的Session public static Session currentSession() throws HibernateException { Session s = (Session) session.get(); // 如果Session还没有打开,atv,则新开一个Session if (s == null) { s = sessionFactory.openSession(); session.set(s); //将新开的Session保存到线程局部变量中 } return s; } public static void closeSession() throws HibernateException { //获取线程局部变量,并强制转换为Session类型 Session s = (Session) session.get(); session.set(null); if (s != null) s.close(); } } 示例是在开启数据库连接的session对象的过程。其实,所有类似于这种缓存对象的代码都一样。首先从ThreadLocal中取当前线程的对象,如果对象为null,就重新创建对象,并把创建好的对象放到ThreadLocal里面。ThreadLocal持有的对象能够保持各个线程之间对象的独立。 ThreadLocal使用步骤 1、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间需要隔离处理的对象xxx。 2、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。 3、在ThreadDemo类的run()方法中,通过getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。 本文作者:易泉梁(点融黑帮),耿直程序猿一枚,会写点代码,喜欢享受生活,上不了厅堂,下得了厨房,喜欢运动,排球(二传),羽毛球,乒乓球水平可以虐菜鸟.人其实是可以快乐地生活的,只是我们自己选择了复杂,选择了叹息! (责任编辑:本港台直播) |