mybloger

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

单例模式

应用场景:在内存中只有一个实例,如xxxFactory,xxxMgr

有八种单例,完美无缺的有两种,常用的却并非这两种

1、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 8:35
 * 饿汉式
 * 类加载到内存后,只有一个实例,JVM保证线程安全
 * 简单使用,推荐实用
 * 唯一缺点:不管用到与否,类装载时就完成实例化
 * (话说你不用它,装在它干嘛)
 */
public class Mgr1 {
    // JVM保证每个class只能load进内存一次,static变量是class load完马上初始化的,保证只能初始化一次
    private static final Mgr1 INSTANCE = new Mgr1(); 

    private Mgr1(){};// 最关键,其他类无法new

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

    public void m(){
        System.out.println("m");
    }

    public static void main(String[] args) {
        Mgr1 mgr11 = Mgr1.getInstance();
        Mgr1 mgr12 = Mgr1.getInstance();
        System.out.println(mgr11 == mgr12);
    }
}


package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 8:35
 */
public class Main {
    public static void main(String[] args) {
        // new Mgr1();new不出来怎么办?只能
        Mgr1 mgr1 = Mgr1.getInstance();
    }
}

2、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 8:59
 * 与Mgr1类似
 */
public class Mgr2 {
    // JVM保证每个class只能load进内存一次,static变量是class load完马上初始化的,保证只能初始化一次
    private static final Mgr2 INSTANCE;
    static {
        INSTANCE = new Mgr2();
    }

    private Mgr2(){};// 最关键,其他类无法new

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

    public void m(){
        System.out.println("m");
    }

    public static void main(String[] args) {
        Mgr2 mgr21 = Mgr2.getInstance();
        Mgr2 mgr22 = Mgr2.getInstance();
        System.out.println(mgr21 == mgr22);
    }
}

3、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 9:04
 * lazy loading
 * 也称懒汉式
 * 虽然达到了按需初始化的目的,但却带来了多线程失效的问题
 */
public class Mgr3 {
    private static Mgr3 INSTANCE;//最开始不初始化

    private Mgr3(){};// 同样的私有构造

    public static Mgr3 getInstance() {
        if (INSTANCE == null) { // 这里有线程问题
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Mgr3(); // 需要的时候初始化
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0;i < 100;i++) {
            new Thread(()->{
                System.out.println(Mgr3.getInstance().hashCode());
            }).start();
        }
    }
}

4、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 9:24
 * 加锁优化了Mgr3,却带来了效率低下的问题
 */
public class Mgr4 {
    private static Mgr4 INSTANCE;//最开始不初始化

    private Mgr4(){};// 同样的私有构造

    public synchronized static Mgr4 getInstance() {
        if (INSTANCE == null) { // 这里有线程问题
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Mgr4(); // 需要的时候初始化
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0;i < 100;i++) {
            new Thread(()->{
                System.out.println(Mgr4.getInstance().hashCode());//  同一个类的不同对象hash码不同
            }).start();
        }
    }
}

5、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 9:29
 * Mgr4的基础上减少锁住的代码量,然而不可行
 */
public class Mgr5 {
    private static Mgr5 INSTANCE;//最开始不初始化

    private Mgr5(){};// 同样的私有构造

    public static Mgr5 getInstance() {
            if (INSTANCE == null) { // 这里有线程问题
                synchronized(Mgr5.class){// 需要时加锁,试图减少锁住的代码量,然而不可行
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                INSTANCE = new Mgr5(); // 需要的时候初始化
            }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0;i < 100;i++) {
            new Thread(()->{
                System.out.println(Mgr5.getInstance().hashCode());//  同一个类的不同对象hash码不同
            }).start();
        }
    }
}

6、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 9:40
 * 双检索,曾经是单例的完美的方案
 */
public class Mgr6 {
    private static Mgr6 INSTANCE;//最开始不初始化

    private Mgr6(){};// 同样的私有构造

    public static Mgr6 getInstance() {
        if (INSTANCE == null) { // 这里有线程问题
                //  双检锁
                synchronized (Mgr6.class) {
                    if  (INSTANCE == null) {
                        try {
                            Thread.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        INSTANCE = new Mgr6(); // 需要的时候初始化
                    }
                }

            }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0;i < 100;i++) {
            new Thread(()->{
                System.out.println(Mgr6.getInstance().hashCode());//  同一个类的不同对象hash码不同
            }).start();
        }
    }
}

7、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 9:48
 * 静态内部类方式
 * JVM保证单例
 * 加载外部类时不会加载内部类
 * 一种完美方案
 */
public class Mgr7 {

    private Mgr7(){}

    private static class Mgr7Holder {// private 修饰保证外部访问不了
        private final static Mgr7 INSTANCE = new Mgr7();// 内部类可以访问外部类私有
    }

    public static Mgr7 getInstance() {
        return Mgr7Holder.INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0;i < 100;i++) {
            new Thread(() -> {
                System.out.println(Mgr7.getInstance().hashCode());
            }).start();

        }
    }
}

8、

package org.ali.singleton;

/**
 * Author: lury
 * Date: 2022-09-04 10:04
 * 不仅可以解决线程同步,还可以防止反序列化
 * 也是完美的 perfect
 * effective java 作者创作的
 */
public enum Mgr8 {
    INSTANCE;

    public static void main(String[] args) {
        for (int i = 0;i < 100;i++) {
            new Thread(() -> {
                System.out.println(Mgr8.INSTANCE.hashCode());
            }).start();

        }
    }
}
posted on 2022-09-04 10:09  万能包哥  阅读(7)  评论(0编辑  收藏  举报