单例模式(八种实现方式)

单例模式八种实现方式

 

1、饿汉单例

/**
 * 饿汉单例
 * 优点:简单、线程安全
 * 缺点:浪费内存(我们的单例对象数量不可控的时候,可能会造成内存浪费)
 */
public class HungraySingleton {
    //类被夹在时,单例对象就已经被创建
    private static final HungraySingleton instance = new HungraySingleton();
    //空参构造器
    public HungraySingleton() {
    }
    //提供全局访问点
    public final static HungraySingleton getInstance(){
        return instance;
    }
}

2、 饿汉单例-静态代码块(装逼)

/**
 * 饿汉静态代码块
 */
public class HungrayStaticSingleton {

    private static final HungrayStaticSingleton instance;

    static {
        instance = new HungrayStaticSingleton();
    }

    public HungrayStaticSingleton() {
    }

    public static HungrayStaticSingleton getInstance(){
        return instance;
    }
}

 3、 懒汉单例

/**
 * 懒汉式
 * 优点:节省资源,性能更高
 * 缺点:线程不安全
 */
public class LazySingleton {

    private static LazySingleton instance;

    public LazySingleton() {
    }
    /**
     *  添加synchronized是可以保障线程安全,但是性能会下降
     */
    public synchronized static final LazySingleton getInstance(){
        if (instance == null){
            instance = new LazySingleton();
        }
        return instance;
    }
}

4、懒汉单例-双重校验锁 

/**
 * 懒汉双重检查锁
 * 优点:性能高,线程安全,避免内存浪费
 * 缺点:不优雅
 *
 */
public class LazyDoubleCheckSingleton {

    private volatile static LazyDoubleCheckSingleton instance;

    public LazyDoubleCheckSingleton() {
    }

    public static final LazyDoubleCheckSingleton getInstance() {
        //双重校验锁 控制是否加锁,主要控制第一次
        if (instance == null) {
            synchronized (LazyDoubleCheckSingleton.class) {
                //控制是否创建对象
                if (instance == null) {
                    instance = new LazyDoubleCheckSingleton();
                    //存在指令重排序  需要加volatile关键字
                }
            }
        }
        return instance;
    }
}

5、懒汉-静态内部类

**
 * 懒汉,静态内部类
 * 优点:性能高,线程安全,避免内存浪费
 * 缺点:不优雅了
 */
public class LazyStaticInnerClassSingleton {

    //巧妙的利用了Java的语法,利用了类加载机制,内部类都是在第一次使用的时候才会被加载,
    // 发生在线程创建之前,一定是线程安全的
    public LazyStaticInnerClassSingleton() {
        //防止有不听话人员通过反射创建对象,但是代码就变得不优雅了
        if (LazyHoldler.instance != null) {
            throw new RuntimeException("不能非法创建单例对象");
        }
    }

    public static final LazyStaticInnerClassSingleton getInstance() {
        return LazyHoldler.instance;
    }

    private final static class LazyHoldler {
        private static final LazyStaticInnerClassSingleton instance = new LazyStaticInnerClassSingleton();
    }
} 

6、枚举单例 (最优雅的单例实现模式)

/**
 * 枚举可以归到饿汉单例中
 * **************************推荐用枚举实现单例******************************
 * 最优雅的单例实现模式就是枚举模式。利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题。
 */
public enum EnumSingleton {
    INSTANCE;
    private String s = null;

    private EnumSingleton() {
        s = new String();
    }

    public String getInstance() {
        return s;
    }
}

7、注册式单例 

/**
 * 容器式单例,是枚举式单例的升级
 * Spring中的做法,就是这种注册式单例
 */
public class ContainerSingleton {

    public ContainerSingleton() {
    }

    private static Map ioc = new ConcurrentHashMap();

    public static Object getInstance(String className) {
        //双重校验锁 判断是否加锁
        if (!ioc.containsKey(className)) {
            synchronized (ioc) {
                //是否创建对象
                if (!ioc.containsKey(className)) {
                    Object obj = null;
                    try {
                        obj = Class.forName(className).newInstance();
                        ioc.put(className, obj);
                    } catch (Exception e) {

                    }
                    return obj;
                } else {
                    return ioc.get(className);
                }
            }
        }
        return ioc.get(className);
    }
}

8、threadLocal实现单例 

/**
 * ThreadLocal 实现单例模式
 * 不能保证整个程序唯一;
 * 可以保证线程唯一;
 * 每个线程中拿到的实例都是一个;
 * 不同的线程拿到的实例不是一个;
 */
public class ThreadLocalSingleton {
    private static final ThreadLocal threadLocalInstanceThreadLocal
            = new ThreadLocal() {
        @Override
        protected ThreadLocalSingleton initialValue() {
            return new ThreadLocalSingleton();
        }
    };

    private ThreadLocalSingleton() {
    }

    public static ThreadLocalSingleton getInstance() {
        return threadLocalInstanceThreadLocal.get();
    }
}
public class ThreadLocalRunnable implements Runnable {
    public void run() {
        ThreadLocalSingleton instance =ThreadLocalSingleton.getInstance();
        System.out.println(Thread.currentThread().getName() + " : " + instance);
    }
}
ThreadLocalSingleton instance = ThreadLocalSingleton.getInstance();
System.out.println(Thread.currentThread().getName() + " : " + instance);
instance = ThreadLocalSingleton.getInstance();
System.out.println(Thread.currentThread().getName() + " : " + instance);
instance = ThreadLocalSingleton.getInstance();
System.out.println(Thread.currentThread().getName() + " : " + instance);
instance = ThreadLocalSingleton.getInstance();
System.out.println(Thread.currentThread().getName() + " : " + instance);
instance = ThreadLocalSingleton.getInstance();
System.out.println(Thread.currentThread().getName() + " : " + instance);

Thread t1 = new Thread(new ThreadLocalRunnable());
Thread t2 = new Thread(new ThreadLocalRunnable());

t1.start();
t2.start();

System.out.println("Program End");

执行结果

main : com.pa.designMode.singleton.ThreadLocalSingleton@65ab7765
main : com.pa.designMode.singleton.ThreadLocalSingleton@65ab7765
main : com.pa.designMode.singleton.ThreadLocalSingleton@65ab7765
main : com.pa.designMode.singleton.ThreadLocalSingleton@65ab7765
main : com.pa.designMode.singleton.ThreadLocalSingleton@65ab7765
Program End
Thread-0 : com.pa.designMode.singleton.ThreadLocalSingleton@2770f418
Thread-1 : com.pa.designMode.singleton.ThreadLocalSingleton@dc7a4fc

 

 

 

 

你可能感兴趣的:(设计模式)