Java设计模式系列——单例模式

1、单例模式的应用场景

单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并且提供一个全局访问点。单例模式是创建型模式,在实际的开发过程中应用广泛,例如J2EE中的ServletContext、ServletContextConfig等,Spring框架中ApplicationContext、数据库连接池等都是单例形式。

2、饿汉式单例模式

饿汉式单例模式在类加载的时候就立即初始化,并且创建单例对象 。因此这种单例模式是天然的线程安全的,在线程还没有出现之前就已经实例化了。
优点:没有任何加锁,执行效率比较高;
缺点:类加载时就初始化,不管用不用都会占用内存,有一定的内存空间浪费。
Spring中ApplicationContext本身就是典型的饿汉式单例模式。

2.1、饿汉式写法一(利用类的初始化机制)

public class HungrySingleTon {
	// Java类初始化顺序:先静态 后动态 --> 先属性 后方法 --> 从上至下
	private static final HungrySingleTon hungrySingleTon = new HungrySingleTon();
	// 私有化构造器
	privite HungrySingleTon() {}
	// 提供全局唯一访问点
	public static HungrySingleTon getInstance() {
		return hungrySingleTon;
	}
}

2.2 、饿汉式写法二(利用静态代码块机制)

public class HungryStaticSingleTon {
	private static final HungryStaticSingleTon hungryStaticSingleTon;
	static {
		hungryStaticSingleTon = new HungryStaticSingleTon();
	}
	private HungryStaticSingleTon() {}
	public static HungryStaticSingleTon getInstance() {
		return hungryStaticSingleTon;
	}
}

饿汉式单例模式的两种写法都比较简单也很好理解,适用于单例对象较少的情况。

3、懒汉式单例模式

懒汉式单例模式的特点是:在外部类调用的时候内部类才会加载。

public class LazySimpleSingleTon {
	private LazySimpleSingleTon() {}
	// 静态块,公共内存区域
	private static LazySimpleSingleTon lazy = null;
	public LazySimpleSingleTon getInstance() {
		if(lazy == null) {
			lazy = new LazySimpleSingleTon();	
		}
		return lazy;
	}
}

上面的代码有一定的概率获得的对象出现不同的实例,意味着这种写法的单例模式不是线程安全的,为了使得懒汉式单例模式在多线程环境下安全,我们给getInstance()方法加上synchronized关键字,使这个方法变成线程同步方法:

public class LazySimpleSingleTon {
	private LazySimpleSingelTon() {}
	private static LazySimpleSingleTon lazy = null;
	public synchronized static LazySimpleSingleTon getInstance() {
		if(lazy == null) {
			lazy = new LazySimpleSingleTon();
		}
		return lazy;
	}
}

但是,用到synchronized关键字总归是要上锁,多线程的情况下锁竞争会有一定的性能损耗。我们从类初始化的角度来考虑,采用静态内部类的方式设计一个更好的方案,这种方案兼顾饿汉式内存浪费问题和懒汉式的性能问题:

public class LazyInnerClassSingleTon {
	// 使用LazyInnerClassSingleTon的时候,默认会初始化内部类
	// 如果没使用,则内部类是不加载的
	private LazyInnerClassSingleTon() {}

	// 每一个关键字都不是多余的,static是为了使单例的空间共享,保证这个方法不会被重写、覆盖
	public static final LazyInnerClassSingleTon getInstance() {
		return LazyHolder.LAZY
	}

	// 默认不加载
	private static class LazyHolder {
		private static final LazyInnerClassSingleTon LAZY = new LazyInnerClassSingleTon();
	}
}

这种方式就是内部类保证在方法调用之前就初始化,巧妙的避免了线程安全的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值