您的位置:首页 > 其它

设计模式-4-单例模式

2016-03-26 15:14 239 查看

单利模式

原理:确保一个类最多只有一个实例,并提供一个全局访问点(构造函数私有化、提供一个静态的方法获取实例)
有些对象我们只需要一个:线程池、缓存、硬件设备(用静态变量的方式实现)

单例的几种实现方法

饿汉式(线程安全 在类的加载的时候就实例一个对象出来,以空间换时间,当这个类太大的时候并且没用到的时候浪费了内存)

public class EagerSingleton {
//创建一个私有的EagerSingleton对象
private static EagerSingleton eagerSingleton = new EagerSingleton();
//私有的构建方法
private EagerSingleton(){};
//静态工厂方法
public static EagerSingleton getInstance(){
return eagerSingleton;
}
}
测试
public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
EagerSingleton eagerSingleton = EagerSingleton.getInstance();
System.out.println(eagerSingleton);

EagerSingleton eagerSingleton1 = EagerSingleton.getInstance();
System.out.println(eagerSingleton1);
}

}
输出相同的地址
EagerSingleton@2a139a55
EagerSingleton@2a139a55


懒汉式(加了一个同步锁解决多线程安全问题 以时间换空间 没人使用的话就不会创建实例节约了内存空间)

public class LazySingleton {
private static LazySingleton lazySingleton = null;
private LazySingleton(){};
//synchronized关键字:同步锁,多线程安全(当线程A正在执行lazySingleton = new LazySingleton();的时候,
//在这个时候刚好有一个线程B执行到if(lazySingleton==null 那么就会执行,这样就实例的两个)
//缺点:同步锁消耗的资源挺多的
public static synchronized LazySingleton getInstance(){
if(lazySingleton==null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
测试
public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
LazySingleton lazySingleton = LazySingleton.getInstance();
System.out.println(lazySingleton);
LazySingleton lazySingleton1 = LazySingleton.getInstance();
System.out.println(lazySingleton1);
}

}
输出相同的地址
LazySingleton@2a139a55
LazySingleton@2a139a55

双重检查加锁(缺点:运行效率不高,不建议使用)

volatile关键字:所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton(){};
public static Singleton getInstance(){
//先检查实例是否存在,不存在才进入下面的同步块
if(singleton==null){
//同步块,线程安全的创建实例
synchronized (Singleton.class) {
//再次检查实例是否存在,不存在才真正的创建实例
if(singleton==null)
singleton = new Singleton();
}
}
return singleton;
}
}
检查
public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
Singleton singleton = Singleton.getInstance();
System.out.println(singleton);
Singleton singleton1 = Singleton.getInstance();
System.out.println(singleton1);
}

}

输出相同的地址
LazySingleton@2a139a55
LazySingleton@2a139a55

Lazy initialization holder class 模式

<pre name="code" class="html">public class Holder {
//构建函数
private  Holder(){};
//类级内部类
private static class SingHolder{

private static Holder holder = new Holder();
}
//通过Holder.getInstance然后调用SingHolder.holder实例化对象
public static Holder getInstance(){

return  SingHolder.holder;
}
}


测试
public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
Holder holder = Holder.getInstance();
System.out.println(holder);
Holder holder1 = Holder.getInstance();
System.out.println(holder1);
}

}

输出相同的地址
LazySingleton@2a139a55
LazySingleton@2a139a55


枚举(最佳实现单例的方法)

public enum Singleton {
INSTANCE;//唯一实例

public static  Singleton getInstance(){
return INSTANCE;
}
}
测试
public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
Singleton enum1 = Singleton.getInstance();
System.out.println(enum1);
Singleton enum2 = Singleton.getInstance();
System.out.println(enum2);
}

}
输出一样的结果
INSTANCE
INSTANCE


总结:

枚举的单例简单方便,但是使用的话自己还是有一些疑问的,所以自己用的话一般选择 Lazy initialization holder class 模式(个人爱好啦~)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式