单例模式从无知到无畏

为啥要有单例

先说三点

  1. 节省资源,有些实例不需要被反复创建和初始化,特别是一些空间占用率高的。比如无状态实例,springbean一般是单例的,主要就是这个原因。
  2. 有些统计性的工作,比如软负载均衡器有时会设计为单例,可以统计单个jvm下负载均衡的分配情况,节点访问次数等。
  3. 暂时没想到

为啥单例模式里的getInstance方法要用static修饰呢

就一个原因,要保证所创建实例的唯一性,为了达到这个目的主要做了三个事:

  1. 构造函数用private修饰,不允许类以外的任何地方new该实例。
  2. 用static修饰实例对象,大家知道用static修饰的成员变量具有全局唯一性。
  3. 通过懒汉或者恶汉模式来保证如果存在实例就不会进行二次创建。

为啥懒汉模式需要双重检查锁定

恶汉模式咱们不说了,比较简单,主要说说懒汉的。为啥要用懒汉,首先就是恶汉这种虽然简单但是比较粗暴,需不需要都要创建,如果对象资源占用比较大就不太划算,这个时候用懒汉,可懒汉是在使用过程中创建的,就设计到一个并发问题,并发问题就又涉及到加锁后的性能问题,首先看一下关键代码。
private LazySingle(){}

	    private static volatile LazySingle inStance;   // (1)
	//双重锁方式
	    public static LazySingle getInstance() throws InterruptedException {
	        if(inStance == null){ //这一层是为了性能   (2)
	            synchronized (LazySingle.class){  //剩下的是为了保证唯一性
	                if(inStance == null){   (3)
	                    Thread.sleep(1000);
	                    inStance = new LazySingle();
	                }
	            }
	        }
	        return inStance;
	    }

在注解(1) 中我们发现用volatile 修饰了一下,目的是多线程修改后的可见性,别到时候其他线程修改了但是本线程看不到,再次创建。
为啥用双重锁就是为了提高性能,先判断下实例是否存在,如果存在那就没锁啥事了,如果没有,好我枷锁,可是在我获取锁的过程中是否会被其他线程创建呢,这个没准,所以我在注视(3)中再次判断是否为null,如果不为null说明被其他线程创建了,如果为null,你再创建实例,这个时候就完美避免了重复创建的问题,注视(3)判断在我获取锁之前是否有人创建了,那么当我获取锁之后别人也就无法创建了,所以是完整的解决掉了并发问题。

java语言的完美解答方法IoDH

通过定义静态内部类的方式完美解决了,饿汉占用资源,懒汉并发资源占用问题,实现比较简单可百度下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值