单例模式

定义

单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)
Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”

单例模式特点

  • 单例类只能有一个实例
  • 单例类必须自己创建自己的唯一实例
  • 单例类必须给所有其他对象提供这一实例

懒汉式

代码实现:
/**
 * @author liouwb
 * 单例模式
 */
public class SingletonPatternTest {
    public static void main(String[] args) {
        // 懒汉式
        SingletonLazy lazy = SingletonLazy.getInstance();
        SingletonLazy lazy1 = SingletonLazy.getInstance();

        // 验证单例是否全局只有一个实例
        System.out.println(lazy == lazy1);

        // 输出对象信息
        System.out.println("lazy :" + lazy);
        System.out.println("lazy1:" + lazy1);
    }
    
    /**
     * 懒汉式
     */
    static class SingletonLazy {
        //
        public static SingletonLazy instance;

        // 私有构造函数
        private SingletonLazy() {
        }

        public static SingletonLazy getInstance() {
            if (instance == null) {
                instance = new SingletonLazy();
            }
            
            return instance;
        }
    }
}
  • lazy和lazy1判断结果输出:
正常获取的实例比较:true

lazy :singleton.SingletonLazyTest$SingletonLazy@4554617c
lazy1:singleton.SingletonLazyTest$SingletonLazy@4554617c

Process finished with exit code 0
结论:
  • 单例模式只有一个实例
  • 懒汉式单例模式,线程不安全

饿汉式

代码实现:
  • 代码演示:
package singleton;


/**
 * @author liouwb
 * 单例模式
 * 饿汉式
 */
public class SingletonHungryTest {
    public static void main(String[] args) {
        // 饿汉式
        SingletonHungry hungry = SingletonHungry.getInstance();
        SingletonHungry hungry1 = SingletonHungry.getInstance();

        // 验证单例是否全局只有一个实例
        System.out.println("饿汉式正常获取的实例比较:" + (hungry == hungry1));
        // 输出对象信息
        System.out.println("hungry :" + hungry);
        System.out.println("hungry1:" + hungry1);
    }

    /**
     * 饿汉式
     */
    static class SingletonHungry {
        private static SingletonHungry instance = new SingletonHungry();

        /**
         * 构造函数
         *
         * @return
         */
        private SingletonHungry() {
        }

        /**
         * @return
         */
        public static SingletonHungry getInstance() {
            
            return instance;
        }
    }
}
  • 实例比较结果:
饿汉式正常获取的实例比较:true

hungry :singleton.SingletonHungryTest$SingletonHungry@4554617c
hungry1:singleton.SingletonHungryTest$SingletonHungry@4554617c

Process finished with exit code 0
结论:
  • 获取实例为同一实例
  • 饿汉模式在类被初始化时就已经在内存中创建了对象,以空间换时间,故不存在线程安全问题

检查锁单例模式

  • 代码采用懒汉式演示,饿汉式代码基本相同,加锁效果一样
  • 代码演示:
package singleton;

/**
 * @author liouwb
 * 单例模式
 * 懒汉式 加锁
 */
public class SingletonLazyLockTest {
    public static void main(String[] args){
        // 懒汉式 加锁
        SingletonLazyLock lazyLock = SingletonLazyLock.getInstance();
        SingletonLazyLock lazyLock1 = SingletonLazyLock.getInstance();

        // 验证单例是否全局只有一个实例
        System.out.println("正常获取的实例比较:" + (lazyLock == lazyLock1));
        
        // 输出相应对象
        System.out.println("lazyLock :" + lazyLock);
        System.out.println("lazyLock1:" + lazyLock1);
    }

    /**
     * 懒汉式 加锁
     */
    static class SingletonLazyLock {
        //
        public static SingletonLazyLock instance;

        // 私有构造函数
        private SingletonLazyLock() {
        }

        public static synchronized SingletonLazyLock getInstance() {
            if (instance == null) {
                instance = new SingletonLazyLock();
            }

            return instance;
        }
    }
}

  • 输出结果:
正常获取的实例比较:true
lazyLock :singleton.SingletonLazyLockTest$SingletonLazyLock@4554617c
lazyLock1:singleton.SingletonLazyLockTest$SingletonLazyLock@4554617c

Process finished with exit code 0
结论:
  • 加锁之后,线程安全

双重检查锁

  • 代码:
package singleton;


/**
 * @author liouwb
 * 单例模式 双重检查锁
 */
public class SingletonDoubleCheckLockTest {
    public static void main(String[] args) {
        // 懒汉式 双重检查锁
        SingletonLazyDoubleLock lazyDoubleLock = SingletonLazyDoubleLock.getInstance();
        SingletonLazyDoubleLock lazyDoubleLock1 = SingletonLazyDoubleLock.getInstance();

        // 验证单例是否全局只有一个实例
        System.out.println("正常获取的实例比较:" + (lazyDoubleLock == lazyDoubleLock1));
        
        // 输出相应对象
        System.out.println("lazyDoubleLock :" + lazyDoubleLock);
        System.out.println("lazyDoubleLock1:" + lazyDoubleLock1);
    }

    /**
     * 懒汉式 双重加锁
     */
    static class SingletonLazyDoubleLock {
        //
        public static SingletonLazyDoubleLock instance;

        // 私有构造函数
        private SingletonLazyDoubleLock() {
        }

        public static synchronized SingletonLazyDoubleLock getInstance() {
            if (instance == null) {
                synchronized (SingletonLazyDoubleLock.class) {
                    if (instance == null) {
                        instance = new SingletonLazyDoubleLock();
                    }
                }
            }

            return instance;
        }
    }
}
  • 结果:
正常获取的实例比较:true
lazyDoubleLock :singleton.SingletonDoubleCheckLockTest$SingletonLazyDoubleLock@4554617c
lazyDoubleLock1:singleton.SingletonDoubleCheckLockTest$SingletonLazyDoubleLock@4554617c

Process finished with exit code 0
结论:
  • 单例只有一个实例
  • 双重检查锁,线程安全

静态内部类

  • 代码:
package singleton;

/**
 * @author liouwb
 * 单例模式 静态内部类
 */
public class SingletonInnerTest {
    public static void main(String[] args) {
        // 单例静态内部类
        SingletonInner inner = SingletonInner.getInstance();
        SingletonInner inner1 = SingletonInner.getInstance();

        // 验证单例是否全局只有一个实例
        System.out.println("正常获取的实例比较:" + (inner == inner1));

        // 输出相应对象
        System.out.println("inner :" + inner);
        System.out.println("inner1:" + inner1);
    }

    /**
     * 单例静态内部类
     */
    static class SingletonInner {
        private SingletonInner() {
        }

        private static class SingleTonHoler {
            private static SingletonInner INSTANCE = new SingletonInner();
        }

        public static SingletonInner getInstance() {
            return SingleTonHoler.INSTANCE;
        }

    }
}
  • 输出结果:
正常获取的实例比较:true
inner :singleton.SingletonInnerTest$SingletonInner@4554617c
inner1:singleton.SingletonInnerTest$SingletonInner@4554617c

Process finished with exit code 0
结论:
  • 输出结果为同一实例
  • 静态内部类单例模式,线程安全

枚举单例

  • 代码
package singleton;


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author liouwb
 * 单例模式 枚举
 */
public class SingletonEnumTest {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 单例 枚举
        SingletonEnum singletonEnum = SingletonEnum.getInstance();
        SingletonEnum singletonEnum1 = SingletonEnum.getInstance();

        // 验证单例是否全局只有一个实例
        System.out.println("正常获取的实例比较:" + (singletonEnum == singletonEnum1));

        // 输出相应对象
        System.out.println("singletonEnum :" + singletonEnum.hashCode());
        System.out.println("singletonEnum1:" + singletonEnum1.hashCode());
    }

    /**
     * 枚举 单例
     */
    enum SingletonEnum {
        INSTANCE;

        public static SingletonEnum getInstance() {
            return INSTANCE;
        }
    }

}
  • 输出结果:
正常获取的实例比较:true
singletonEnum :1163157884
singletonEnum1:1163157884

Process finished with exit code 0
结论:
  • 输出结果为同一实例
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页