ThreadLocal与Synchronized

package com.demo;



import org.hibernate.HibernateException;
import org.hibernate.classic.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;


public final class HibernateUtil {
    private static SessionFactory sessionFactory;//现实中需要考虑属性的线程安全问题
    /*
    创建线程局部变量threadLocal,用来保存Hibernate的Session
    ThreadLocal在其中设置任何对象,该对象对特定的线程访问将是“全局”且“局部”
    全局:意味着这个线程的任何地方都可以访问到
    局部:每个线程拥有它自己的ThreadLocal变量,一个线程不能访问或修改其他线程的ThreadLocal变量
     */
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    //使用静态代码块 初始化Hibernate
    static{
        try{
            Configuration cfg = new Configuration().configure();
            sessionFactory = cfg.buildSessionFactory();
        }catch (HibernateException ex) {  
           // throw new RuntimeException("Exception building SessionFactory: "  
             //       + ex.getMessage(), ex);  
        }  
    }
    //获得ThreadLocal对象管理的session实例
    /*
     * 单一实例:在系统中全局使用一个唯一的SessionFactory实例,主要原因是Factory只需要一个实例可以调用方法就可以
     * 另一个方面取得SessionFactory需要的时间太久,每次都实例化,会过分得浪费系统CPU资源
     * 每个线程和使用自身对应的数据库连接session:这里是为每个线程建立一个局部的变量来达到这个目的
     */
    public synchronized static Session getSession(){//同步锁  排队等候访问
        /*
        里面执行先取得当前线程的ThreadLocalMap 然后将threadSession作为key将对应的值取出
         */
        Session s = (Session)threadLocal.get();//s--线程 私有
        if(s==null){// 判断当前线程有无放进去session
            s = sessionFactory.openSession();//创建一个session
            //将新打开的session实例保存到线程局部变量threadLocal中
            threadLocal.set(s);//实际上放到当前线程的ThreadLocal中
        }
        return s;
    }
    //关闭session实例
    //@throws HibernateException
    public static void closeSession() throws HibernateException{
        //从线程局部变量threadLocal中获取之前存入的Session实例
        Session session = threadLocal.get();
        threadLocal.set(null);
        if(session!=null){
            session.close();
        }
    }
    //获得sessionFactory的实例
    public static SessionFactory getSessionFactory(){
        if(sessionFactory == null){
            Configuration cfg = new Configuration().configure();
            sessionFactory = cfg.buildSessionFactory();
        }
        return sessionFactory;
    }
    //关闭sessionFactory
    public static void closeSessionFactory(){
        if(!sessionFactory.isClosed()){    //避免潜在的多线程并发问题
            sessionFactory.close();
        }
    }
}
/*
threadLocal.set(session);将新创建的对象的引用保存到各线程的一个map中,每个线程都有这样的一个map
执行threadLocal.get()时,各线程从自己的map中取出放进去的对象 取出的是各自的对象
顺便说一下: synchronized(时间换空间 同步-仅仅提供一份变量 让不同的线程去排队访问)
            ThreadLocal(空间换时间  并发性-为每一个线程都提供一份变量 因为可以同时访问而互不影响)
 * new Configuration.configure() 会在默认的路径下找hiberate.cfg.xml配置文件,请看源代码: 

Java代码  收藏代码
public Configuration configure() throws HibernateException {  
    configure( "/hibernate.cfg.xml" );  
    return this;  
}

所以你应该是: 
Java代码  收藏代码
Configuration.configure("/hiberate.cfg.xml")

*Configuration是hibernate的入口,在新建一个Configuration的实例的时候,
*使用不带参数的configure ()方法,hibernate会在classpath里面查找配置文件;
*Configuration的configure ()方法还支持带参数的访问方式,你可以指定hbm.xml文件的位置,
*而不是使用默认的classpath下面的配置文件。应该指定配置文件的位置。/
**/
package com.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {

    // SessionFactory全局只需要有一个就可以了
    private static SessionFactory sessionFactory;

    static {
        Configuration cfg = new Configuration();
        // cfg.configure(); // 读取默认的配置文件(hibernate.cfg.xml)
        // // cfg.configure("hibernate.cfg.xml"); // 读取指定位置的配置文件
        // sessionFactory = cfg.buildSessionFactory();

        // cfg.addResource("cn/itcast/a_helloworld/User.hbm.xml");
        // cfg.addClass(User.class); // 去User类所在的包中查找名称为User,后缀为.hbm.xml的文件

        // 初始化SessionFactory
        sessionFactory = new Configuration()//
                .configure()//
                .buildSessionFactory();
        
    }

    /**
     * 获取全局唯一的SessionFactory
     * 
     * @return
     */
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    /**
     * 从全局唯一的SessionFactory中打开一个Session
     * 
     * @return
     */
    public static Session openSession() {
        return sessionFactory.openSession();
    }
}

 

posted @ 2017-09-03 20:09  starskyhu  阅读(291)  评论(0编辑  收藏  举报