(创建型)设计模式——单例模式(singleton)

ps:单例模式有很多种实现方法,以下介绍5种常见的使用方法和一种《Effective Java》中提过的一种实现方法,但是不常用。

在这里插入图片描述
1、饿汉式。缺点:不管有没有使用,在类装载时就已经加载内存中。

/*
饿汉式
缺点:不管用到与否,类装载时就完成实例化
 */
public class Mgr01 {
 
   //在Mgr01被类加载器load到内存中就调用私有构造方法实例化(迫不及待,所以称为饿汉)	
   private static  final  Mgr01 INSTANCE = new Mgr01();
	  
   /*
    构造方法私有化,在外部无法调用
   */
 	private Mgr01(){}
	
	
	public static Mgr01 getMgro1() {
	      return INSTANCE;
	  }
	
 	public static void main(String[] args) {

	      Mgr01 mgr01 = Mgr01.getMgro1();
	      Mgr01 mgr02 = Mgr01.getMgro1();

	      System.out.println(mgr01==mgr02);

  	 }

}

2、懒汉式。缺点:虽然可以按需加载,多线程并发的时候,容易产生多个实例。

/*
懒汉式
缺点:虽然可以按需加载,但是多线程并发的时候,容易创建多个实例
 */
public class Mgr02 {
  
  private static Mgr02 INSTANCE;

  private Mgr02(){}
  
  //在需要的时候,再进行获取单例对象(所以叫做懒汉式)
  public static Mgr02 getMgro1() {
	   //如果第一次获取,那我们需要进行实例化
       if (INSTANCE==null){
			
		   //当多线程并发的话,可能有多条线程执行到此部分,所以获得到不同的实例对象
           try {
               Thread.sleep(1000);
           }catch (Exception e){

           }

           INSTANCE = new Mgr02();

       }

        return INSTANCE;
   }

   public static void main(String[] args) {
   	   //多线程测试
       for (int i = 0; i < 100; i++) {
           //lamda表达式
           new Thread(()->{
               System.out.println(Mgr02.getMgro1().hashCode());
           }).start();
       }
   }
}

3、懒汉式1.0版本。缺点:解决了多线程并发获取的实例不为单例的问题,但是执行效率较低。

/*
懒汉式

方法上加synchronized锁,但是多线程时候的执行效率较低
 */
public class Mgr03 {

  private static Mgr03 INSTANCE;

  private Mgr03(){}

    //方法上加同步锁,保证此方法每次只能让一个线程使用
    public synchronized static Mgr03 getMgro1() {
        if (INSTANCE==null){
            try {
                Thread.sleep(1000);
            }catch (Exception e){

            }
            INSTANCE = new Mgr03();
        }

         return INSTANCE;
    }

    public static void main(String[] args) {

        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Mgr03.getMgro1().hashCode());
            }).start();
        }

    }

4、懒汉式2.0版本(双重检测锁,可以说是比较完美的。但是写的比较复杂)


/*
懒汉式

不在方法上加synchronized锁,而是
 */
public class Mgr05 {

  private static volatile Mgr05 INSTANCE;

  private Mgr05(){}

    public static Mgr05 getMgro1() {

       //双重检测锁
        if (INSTANCE==null){
            synchronized (Mgr05.class){
            	//如果不加此判断,那么在上面第一个if判断语句,可能同时进来两个线程,就算锁住这部分代码块,依然会产生不同的实例
                if(INSTANCE==null){
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e){

                    }
                    INSTANCE = new Mgr05();
                }
            }
        }
         return INSTANCE;
    }

    public static void main(String[] args) {

        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Mgr05.getMgro1().hashCode());
            }).start();
        }
    }

5、静态内部类方式(完美)。

/*
静态内部类方式
JVM保证单例
加载外部类的时候不会加载内部类,这样可以实现需要的时候再加载
 */
public class Mgr06 {

  private Mgr06(){}

  //内部类,用来获取单例
  private static class Mgr06Holder{

      private final  static Mgr06 INSTANSE =  new Mgr06();

  }

    public synchronized static Mgr06 getMgro1() {
        return Mgr06Holder.INSTANSE;
    }

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

5、使用枚举实现(代码简洁,保证单例,而且可以防止反序列化)

public enum Mgr07 {

    INSTANCE;

    public void m(){}

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

}

总结:推荐使用第1种和第5种实现方法,简单优雅。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值