//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
private Singleton() {}
private static Singleton single=null;
//静态工厂方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}
两者区别:
1:
饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,
懒汉式本身是非线程安全的,为了实现线程安全三种方法解决:
1:在getInstance方法上加同步
public static synchronized Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
2:
双重检查锁定
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
3:
静态内部类
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
2:资源加载和性能
饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,
而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
至于1、2、3这三种实现又有些区别,
第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,
第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗
第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。
3:应用
懒汉式:
1:保证一个数据库对应一个sessionFactory
2:保证同一个客户端用户使用同一个session对象
public class HibernateSessionFactory {
private static SessionFactory sessionFactory;
// 使用本地线程对象管理session对象
private final static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
// 保证满足第一个条件
static {
buildSessionFactory();
}
/**
* 定义构建SessionFactory对象的方法 2017年4月14日
*
* @return SessionFactory buildSessionFactory
*/
public static void buildSessionFactory() {
// 判断SessionFactory是否为空
if (sessionFactory == null) {
Configuration cfg = new Configuration().configure();
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties())
.build();
sessionFactory = cfg.buildSessionFactory(serviceRegistry);
}
}
/**
* 定义获取session的方法
* 2017年4月14日
* @return
* Session
* getSession
*/
public static Session getSession() {
// 从本地线程中获取Session对象
Session session = threadLocal.get();
// 判断session为null需要把创建的session对象方法放到本地线程中
if (session == null) {
// 判断sessionFactory为空
if(sessionFactory == null){
buildSessionFactory();
}
session = sessionFactory.openSession();
// 设置到本地线程中
threadLocal.set(session);
}
return session;
}
public static void closeSession(){
Session session = threadLocal.get();
if(session.isConnected() && session!=null){
session.close();
session = null;
threadLocal.set(null);
}
}
}
jdbc属性文件解析类
public class PropertiesParser extends Properties {
private PropertiesParser() {
}
/**
*
*/
private static final long serialVersionUID = 1L;
private static PropertiesParser pp;
// 装载属性文件
{
try {
this.load(this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 定义创建当前类实例的静态的方法
*/
public static PropertiesParser newInstance() {
if (pp == null) {
pp = new PropertiesParser();
}
return pp;
}
/**
* 定义通过属性文件中对应key获取值得方法
*/
public String getValueByKey(String key) {
return getProperty(key);
}
}