设计模式之单例

一 概念

       单例模式:顾名思义就是只能实例化一个对象的设计模式。很多开发人员一听到单例模式,都会觉得很简单,对于这样的同学,我想问一下,你真的理解单例模式吗? 单例模式有多少种写法? 单例模式的DCL?DCL为啥需要需要用到valitile?等问题都理解么?作为一个程序员,咱话不多说,带着问题撸代码。

二  单例模式实战

       1 饿汉模式

                    饿汉模式代码如下:

public class Singleton01 {
	
	//恶汉模式需要提前实例化一个类对象
	private static Singleton01 signleton01 = new Singleton01();
	
	//私有化构造器
	private Singleton01(){};
	
	//提供一个方法去实例化对象
	public static Singleton01 getInstance(){
		return signleton01;
	}

}

                  饿汉模式代码简单,但是有一个问题,就是在没有用到这个类的时候,jvm虚拟机加载类的时候也会实例化这个对象。

      2 饱汉模式

                 饱汉模式代码如下:


public class Singleton02 {
	
	//饿汉模式提前不会实例化对象,只有等到需要用的时候才会实例化
	private static Singleton02 singleton02 = null;
	
	//私有化构造器
	private Singleton02(){};
	
	//利用同步锁来实现线程安全
	public static synchronized Singleton02 getInstance(){
		if(singleton02 == null){
			singleton02 = new Singleton02();
		}
		return singleton02;
	}

}

              饱汉模式的方法会有一个问题,就是同步锁的效率很低,会影响到效率。

    3 饱汉模式DCL模式

                饱汉DCL模式代码如下:

public class Singleton03 {
	
	//饿汉模式提前不会实例化对象,只有等到需要用的时候才会实例化, 通过volatile关键字来实现禁止指令重排序
	private static volatile Singleton03 singleton03 = null;
	
	//私有化构造器
	private Singleton03(){};
	
	//利用同步代码块来实现线程安全,从而在同步方法的基础上提高了效率
	public static Singleton03 getInstance(){
		if(singleton03 == null){
			synchronized(Singleton03.class){
				if(singleton03 == null){
					singleton03 = new Singleton03();
				}
			}
		}
		return singleton03;
	}

}

             饱汉模式的DCL下必须要加上volatile关键字。原因如下在new Singleton03();这段代码在执行的时候有3个阶段,第一步 申请一块内存空间,这个时候这个类的所有属性都是默认值。第二步 初始化类对象属性, 第三步 实例化对象。如果没有加volatile关键        字的话,那么jvm在编译class的时候会出现指令重排序的现象。导致第二步和第3步顺序调换(概率很小,但是存在)。这样会导致属性值丢失的情况。    

    4 枚举的方式实现单例模式 

               枚举的方式实现单例模式的代码如下:

public  enum Singleton04 {
	instance;
}

             枚举的方式可以实现单例,还可以防止反序列化。

    5 通过静态内部类的方式来实现单例模式

             静态内部类的方式来实现单例模式的代码如下:

public class Singleton05 {
	private static class Singleton05Hoder{
		private static Singleton05 singleton05 = new Singleton05();
	}
	
	private static Singleton05 getInstatnce(){
		return Singleton05.Singleton05Hoder.singleton05;
	}
	
	public static void main(String[] args){
		for(int i=0; i<100; i++){
			new Thread(new Runnable(){
				@Override
				public void run() {
					System.out.println(Singleton05.getInstatnce().hashCode());
				}
			}).start();
		}
	}
}

      6 通过容器的方式来实现单例模式   

               通过容器的方式来实现单例模式的代码如下:

import java.util.concurrent.ConcurrentHashMap;

public class Singleton06 {
	private static ConcurrentHashMap<String, Singleton06> map = new ConcurrentHashMap<String, Singleton06>();
	
	public static Singleton06 getInstance(String key){
		map.putIfAbsent(key, new Singleton06());
		return map.get(key);
	}

	public static void main(String[] args){
		for(int i=0; i<100; i++){
			new Thread(new Runnable(){
				@Override
				public void run() {
					System.out.println(Singleton06.getInstance("Singleton06").hashCode());
				}
			}).start();
		}
	}

}

        容器方式实现单例得需要使用ConcurrentHashMap来保证线程安全。 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值