单例模式有很多种,在这里就介绍三种:懒汉式单列,饿汉式单列,登记式单列。
单列模式有一下几个特点:1.单例类只能有一个实例 2.单例类必须自己创建自己的唯一实例 3.单例类必须为其他所有对象提供这一实例
目的:就是为了避免不一致的状态
一.懒汉式单例
//懒汉式单例,在第一次调用的时候实例化自己
public class singleton{
private singleton(){};
private static singleton single=null;
private static singleton getInstence(){
if(single==null){
single=new singleton();
}
return single;
}
}
singleton将类构造方法设置为private为了避免被外部类实例化,在同一个虚拟机的范围内,singleton的唯一实例只能通过getInstence得到。
(事实上,java的反射机制能够实现构造方法为private类的),懒汉式方法的线程是极其不安全的,通过:
1.在getInstence方法上加上同步
public static synchronized singleton getInstence(){
if(single==null){
single=new singleton();
}
return single;
}
2.双重检查锁定
public static singleton getInstence(){
if(single==null){
single=new singleton();
}
return single;
}
3.静态内部类
public class singleton(){
private static class LazyHolder{
private static final singleton INSTENCE =new singleton();
private singleton();
public static final singleton getInstence(){
return LazyHolder.INSTENCE;
}
}
}
这种方法比上面的那两种性能上要更好一些
二.饿汉式单例
//饿汉式单例在类初始化的时候已经自行实例化
public static singleton2{
private singleton2();
private static final singleton2 single2=new singleton2(();
//静态工厂方法
public static singleton2 getInstence(){
return single2;
}
}
饿汉式在类创建的时候就已经创建好一个静态的的对象供系统使用,以后不再改变所以线程是安全
三.登记式单例
//类似spring里面的方法,将类名注册,下次直接从里面获取。
public class singleton3{
private static Map<String,singleton3> map=new HashMap<String,singleton3>();
static{
singleton3 single=new soingleton3();
map.put(single.getClass().getName(),single);
//保护的默认的构造子方法
protected singleton3();
//静态工厂方法,返回此类的唯一实例
public static singleton3 getInstence(String name){
if(name==null){
name=singleton3.class.getName();
if(map.get(name)==null){
map.put(name,Class.forname(name).newInstence());
}
return map.get(name);
}
}
}
}