我想在使用hibernate或者mybatis时,大家都接触过单例模式
单例模式分为两种: 懒汉和饿汉
懒汉:使用时才去创建--看着名字就能想到
饿汉:一开始就去创建
分别上代码:
懒汉:
public class Singlelazy {
public static FactoryCopy copy;
public static FactoryCopy getFc(){
if(copy==null){
return copy=new FactoryCopy();
}
return copy;
}
private Singlelazy{
}
}
饿汉:
public class Siglehungry {
private static FactoryCopy copy=new FactoryCopy();
private Siglehungry() {
// TODO 自动生成的构造函数存根
}
public static FactoryCopy getFactoryCopy(){
return copy;
}
说说两者区别:
懒汉在使用时候,在使用的时候才去创建,那么在响应时间上会更长。并且线程不安全;
饿汉模式一开始就创建了,但是有可能在后面我们没有使用到这个对象,如果创建的对象过于庞大的话,会造成资源的浪费,但是它是线程安全的;
线程不安全那么问题就大了,那么我们也可以吧懒汉模式写成线程安全;
想要实现线程安全,其实最常用到的就是加锁了
public class Singlelazy {
public static volatile FactoryCopy copy;
public static synchronized FactoryCopy getFc(){
if(copy==null){
return copy=new FactoryCopy();//A
}
return copy;
}
}
但是 本着减小锁粒度的原则,我们还可以这么写
public class Singlelazy {
public static volatile FactoryCopy copy;//必须使用volatile
public static FactoryCopy getFc(){
if(copy==null){//如果重排序这里会出现问题 当线程A运行到赋值时,重排序,B运行到当前行,不为空,但是还没初始化,就会出错,所以需要加volatile
synchronized(Singlelazy.class){
if(copy==null){
return copy=new FactoryCopy();//A
}
}
}
return copy;
}
}
最后,还可以使用枚举来实现单例
package com.czy.designmodel;
public class UserESingle {
public static void main(String[] args) {
System.out.println(UserESingle.getUserESingle().hashCode());
System.out.println(UserESingle.getUserESingle().hashCode());
}
private UserESingle() {
// TODO 自动生成的构造函数存根
}
public static UserESingle getUserESingle(){
return Sigle.Mysigle.getUserESingle();
}
private enum Sigle{
Mysigle;//表示是一个Sigle对象
private UserESingle eSingle;
private Sigle() {
// TODO 自动生成的构造函数存根
eSingle=new UserESingle();
}
private UserESingle getUserESingle(){
return eSingle;
}
}
}