为什么使用TreadLocal来实现?
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 下面以 Hibernate 中的 session(相当于MyBatis中的 SqlSession)来示范。
创建类 SessionUtil.java
importorg.hibernate.Session; importorg.hibernate.SessionFactory; importorg.hibernate.cfg.Configuration; publicclassSessionUtil { privatestaticSessionFactoryfactory; privatestaticThreadLocal<Session>threadLocal=newThreadLocal<Session>(); // 静态初始化块,加载配置信息,获取SessionFactorystatic { // 读取hibernate.cfg.xml文件Configurationcfg=newConfiguration().configure(); // 建立SessionFactoryfactory=cfg.buildSessionFactory(); } publicstaticSessiongetSession() { //获取当前线程下的sessionSessionsession=threadLocal.get(); //如果session为null,则从SessionFactory中获取一个session放入ThreadLocalif(session==null) { System.out.println("session is null!"); session=factory.openSession(); threadLocal.set(session); } returnsession; } publicstaticvoidcloseSession() { Sessionsession=threadLocal.get(); //如果session不为null,则关闭session,并清空ThreadLocalif(session!=null) { session.close(); threadLocal.set(null); } } }
创建 MyThread.java 并继承 Thread 类
importorg.hibernate.Session; publicclassMyThreadextendsThread{ @Overridepublicvoidrun() { Sessionsession1=SessionUtil.getSession(); Sessionsession2=SessionUtil.getSession(); Sessionsession3=SessionUtil.getSession(); //获取线程idlongthreadId=this.getId(); //输出session的hashCode,分辨是否是同一个session实例System.out.println("线程"+threadId+":\n"+session1.hashCode() +"\n"+session2.hashCode() +"\n"+session3.hashCode()); } }
创建 Test.java
publicclassTest { publicstaticvoidmain(String[] args) { MyThreadthread1=newMyThread(); MyThreadthread2=newMyThread(); MyThreadthread3=newMyThread(); //启动线程thread1.start(); thread2.start(); thread3.start(); } }
结果截图:
附:
结论
- 从结果中的 hashCode 可以看出,每条线程都有属于自己的一个 session 实例。