设计模式之单例模式


设计模式之单例模式

1、饿汉单例模式(静态常量)

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午10:41
 * @Description: 饿汉单例模式(静态常量)
 */

/**
 *  优点:类加载的时候就完成类的实例化,没有线程同步的问题,实现比较简单
 *
 *  缺点:没有达到懒加载的效果,如果从始至终没用过,就有点浪费内存
 */
public class Test01 {
    public static void main(String[] args) {
        Singer singer1 = Singer.getInstance();
        Singer singer2 = Singer.getInstance();
        System.out.println(singer1 == singer2);
        System.out.println(singer1.hashCode());
        System.out.println(singer2.hashCode());
    }
}

class Singer {
    //1.私有化构造方法
    private Singer () {

    }

    //2.构造内部创建对象实例
    private final static Singer INSTANCE = new Singer();

    //3.静态公有的获得实例方法
    public static Singer getInstance() {
        return INSTANCE;
    }
}

2、 单例模式 饿汉(静态代码块)应用实例

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午10:52
 * @Description: 单例模式 饿汉(静态代码块)应用实例
 */

/**
 * 优点:简单,不存在线程同步问题
 * 缺点:可能浪费内存空间
 */
public class Test02 {
    public static void main(String[] args) {
        Singer02 singer1 = Singer02.getInstance();
        Singer02 singer2 = Singer02.getInstance();
        System.out.println(singer1 == singer2);
        System.out.println(singer1.hashCode());
        System.out.println(singer2.hashCode());
    }
}

class Singer02 {
    private Singer02 (){

    }

    private static Singer02 INSTANCE;

    static {
        INSTANCE = new Singer02();
    }

    public static Singer02 getInstance() {
        return INSTANCE;
    }

}

3、懒汉(线程不安全的写法)

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午11:00
 * @Description: 懒汉(线程不安全的写法)
 */

/**
 * 优点: 实现类懒加载效果,是能在单线程。
 * 缺点:执行获得实例的时候,如果一个线程进去了还没创建,这时候另一个也近来了,就会创建两个实例,破坏了单例模式
 */
public class Test03 {
    public static void main(String[] args) {
        Singer03 singer1 = Singer03.getInstance();
        Singer03 singer2 = Singer03.getInstance();
        System.out.println(singer1 == singer2);
        System.out.println(singer1.hashCode());
        System.out.println(singer2.hashCode());
    }
}

class Singer03 {
    private static Singer03 instance;

    private Singer03(){

    }

    //提供一个静态创建方法,当使用类实例的时候创建
    public static Singer03 getInstance() {
        if(instance == null){
            instance = new Singer03();
        }
        return instance;
    }

}

4、懒汉(线程安全,同步方法)

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午11:05
 * @Description: 懒汉(线程安全,同步方法)
 */

/**
 * 优点:解决了线程不安全
 *
 * 缺点:方法进行同步的话效率低
 */
public class Test04 {
    public static void main(String[] args) {
        Singer04 singer1 = Singer04.getInstance();
        Singer04 singer2 = Singer04.getInstance();
        System.out.println(singer1 == singer2);
        System.out.println(singer1.hashCode());
        System.out.println(singer2.hashCode());
    }
}

class Singer04 {
    private static Singer04 instance;

    private Singer04(){}

    /**
     * synchronized 在静态方法和成员方法上的区别?
     * https://blog.csdn.net/ethanhola/article/details/90445131
     * @return
     */
    public static synchronized Singer04 getInstance(){
        if(instance == null){
            instance = new Singer04();
        }
        return instance;
    }
}

5、懒汉(线程安全,同步代码块)

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午11:10
 * @Description: 懒汉(线程安全,同步代码块)
 */
public class Test05 {
    public static void main(String[] args) {

    }
}
class Singer05 {
    private static Singer05 instance;

    private Singer05(){}

    /**
     * 不能保证线程安全。不推荐使用
     * @return
     */
    public static Singer05 getInstance(){
        if(instance == null){
            synchronized (Singer05.class){
                instance = new Singer05();
            }

        }
        return instance;
    }
}

6

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午11:14
 * @Description: 推荐使用 实现懒懒加载 线程安全问题,保证效率
 *  两次检查,实例化只执行一次,延迟加载也完成懒
 */
public class Test06 {
    public static void main(String[] args) {
        Singer06 singer1 = Singer06.getInstance();
        Singer06 singer2 = Singer06.getInstance();
        System.out.println(singer1 == singer2);
        System.out.println(singer1.hashCode());
        System.out.println(singer2.hashCode());
    }
}

class Singer06 {

    // volatile 防止指令重排
    private static volatile Singer06 instance;

    private Singer06(){}

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

7

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午11:25
 * @Description: 静态内部类创建单例  推荐使用
 * 分析:
 * 在类加载的时候,静态内部类是不会加载的,这样依赖实现类懒加载,节省了内存空间
 * 调用创建实例的方法也是线程安全的
 */
public class Test07 {
    public static void main(String[] args) {
        Singer07 singer1 = Singer07.getInstance();
        Singer07 singer2 = Singer07.getInstance();
        System.out.println(singer1 == singer2);
        System.out.println(singer1.hashCode());
        System.out.println(singer2.hashCode());
    }


}

class Singer07 {
    private Singer07() {}

    //写一个静态内部类  final会进行内部优化
    private static class SingerInstance {
        private static final Singer07 INSTANCE = new Singer07();
    }

    //静态公有方法
    public static Singer07 getInstance(){
        return SingerInstance.INSTANCE;
    }
}

8

package sjms.dlms;

/**
 * @Author: suny
 * @Date: 2021/11/05 下午11:32
 * @Description: 枚举类实现单例  枚举JDK1.5增加
 * 优点: 避免多线程嗯题,防止反序列化重写创建对象问题
 */
public class Test08 {
    public static void main(String[] args) {
        Singer09 singer = Singer09.INSTANCE;
        Singer09 singer1 = Singer09.INSTANCE;
        System.out.println(singer1 == singer);
        System.out.println(singer.hashCode());
        System.out.println(singer1.hashCode());
    }
}
// 枚举的每个属性都是一个对象
enum Singer09{
    //属性
    INSTANCE;

    public void method() {
        System.out.println("Hello SunY!");
    }
}

文章作者: fejxc
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fejxc !
评论
  目录