创建型模式之-单例模式

创建型设计模式之单例模式

简介

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
在这里插入图片描述

注意⚠️:

  • 单例类只能有一个实例
  • 单例类必须通过自己创建自身的实例
  • 单例类必须为所有类提供自身的唯一实例

单例模式的实现有很多种:

  • 懒汉式
  • 饿汉式 常用
  • DCL双检锁模式(double-check-lock) 常用
  • 静态Holder模式 常用
  • 枚举 可以使用

要实现单例模式,需要完成以下几点:

1、私有化构造器,不能通过new来创建该类的实例

2、将自身对象作为自身的私有化静态属性

3、通过getInstance()方法获取实例

1 懒汉式

懒汉式本身不能保证线程安全,但是能保证lazy装载,假如懒汉式样需要保证线程安全,需要用到synchronized关键字修饰获取实例的方法。

1.1 线程不安全懒汉式

package com.shufang.create_type.allsingletons;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 1、延迟加载
 * 2、线程不安全
 * 3、懒汉式
 */
public class NotSafeLazySingleton {

    private static NotSafeLazySingleton notSafeLazySingleton;

    private NotSafeLazySingleton() {
        System.out.println("initailizing");
    }

    public static NotSafeLazySingleton getInstance() {
        if (notSafeLazySingleton == null) {
            notSafeLazySingleton = new NotSafeLazySingleton();
        }
        return notSafeLazySingleton;
    }

    public static void main(String[] args) {

        /**
         * initailizing
         * initailizing
         * initailizing
         * initailizing
         * com.shufang.create_type.allsingletons.NotSafeLazySingleton@6419af39
         * com.shufang.create_type.allsingletons.NotSafeLazySingleton@b20b63
         * com.shufang.create_type.allsingletons.NotSafeLazySingleton@6419af39
         * com.shufang.create_type.allsingletons.NotSafeLazySingleton@6419af39
         * TODO 构造器被调用了4次,说明在多线程的情况下,构造器被调用了4次
         */
        ExecutorService pool = Executors.newFixedThreadPool(10);

        for (int i = 1; i < 50; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(NotSafeLazySingleton.getInstance());
                }
            });

            pool.shutdownNow();
        }
    }
}

1.2 线程安全的懒汉式

package com.shufang.create_type.allsingletons;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 线程安全的懒汉式单例模式
 * 延迟加载
 * 线程安全
 * 懒汉式
 * NOTE:懒汉式没有将方法加synchronized修饰的会有线程安全问题
 */
public final class SafeLazySingleton {
    //私有化静态属性
    private static SafeLazySingleton safeLazySingleton;

    //私有化构造器
    private SafeLazySingleton() {
        System.out.println("inited");
    }

    //静态方法获取实例对象
    public static synchronized SafeLazySingleton getInstance() {
        if (safeLazySingleton == null) {
            safeLazySingleton = new SafeLazySingleton();
        }
        return safeLazySingleton;
    }

    // 测试利用多线程创建该实例
    public static void main(String[] args) {
        //创建固定数量线程池
        ExecutorService pool = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 50; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(SafeLazySingleton.getInstance());
                }
            });
        }
        pool.shutdownNow();
    }
}

2 饿汉式

饿汉式能保证线程安全,但是不能保证延迟加载

package com.shufang.create_type.allsingletons;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 可能会产生垃圾对象
 * 饿汉式在调用该类的时候装载该实例属性,比较常用
 */
public final class HungrySingleton {
    private static HungrySingleton hungrySingleton = new HungrySingleton();

    private HungrySingleton() {
        System.out.println("inited");
    }

    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }


    public static void main(String[] args) {

        ExecutorService pool = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 50; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(HungrySingleton.getInstance());
                }
            });
        }
        pool.shutdownNow();

    }
}

3 双检锁模式

双检锁模式又称为double-check-lock,能保证延迟加载,也可以保证线程安全

package com.shufang.create_type.allsingletons;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * double-check lock
 */
public class DCLSingleton {
    //使用volatile关键字开启线程之间的内存可见性,但是不支持原子性,
    private volatile static DCLSingleton dclSingleton;

    private DCLSingleton() {
        System.out.println("inited");
    }

    public static DCLSingleton getInstance() {
        if (dclSingleton == null) {
            synchronized (DCLSingleton.class) {
                if (dclSingleton == null) {
                    dclSingleton = new DCLSingleton();
                }
            }
        }

        return dclSingleton;
    }

    /**
     * 测试该创建是否为单例模式
     * @param args
     */
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 50; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(DCLSingleton.getInstance());
                }
            });
        }
        pool.shutdownNow();
    }
}

4 静态内部类Holder模式

该模式能实现与双检锁一样的效果,线程安全,且延迟加载

package com.shufang.create_type.allsingletons;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public final class StaticInnerHolderSingleton {

    //1 私有化构造器
    private StaticInnerHolderSingleton() {
        System.out.println("inited");
    }

    //创建静态内部类,这个成员的初始化也是延迟加载的,只有在调用的时候会装载该内部类
    private static class Holder {
        static final StaticInnerHolderSingleton INSTANCE = new StaticInnerHolderSingleton();
    }

    //获取实例
    public static StaticInnerHolderSingleton getInstance() {
        return Holder.INSTANCE;
    }


    /**
     * 测试实例的创建
     * inited,构造器只被调用一次
     * com.shufang.create_type.allsingletons.StaticInnerHolderSingleton@be30631
     * ......
     * @param args
     */
    public static void main(String[] args) {

        ExecutorService pool = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 50; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(StaticInnerHolderSingleton.getInstance());
                }
            });
        }
        pool.shutdownNow();
    }

}

5 枚举实现单例

通过枚举实现单例,代码简洁,但是目前少用

import java.util.concurrent.Executors;

/**
 * 枚举可以实现单例模式,而且代码简介,但是目前不太常用
 */
enum EnumSingleton {
    INSTANCE;
		//枚举类的构造器默认就是private的
    EnumSingleton() {
        System.out.println("inited");
    }

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);

        /**
         * inited  构造器只被调用了一次
         * com.shufang.create_type.allsingletons.EnumSingleton
         * com.shufang.create_type.allsingletons.EnumSingleton
         */
        for (int i = 0; i < 50; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(EnumSingleton.INSTANCE.getClass().getName());
                }
            });
        }
        pool.shutdownNow();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值