设计模式:单例模式
什么是单例模式?
单例是指在程序运行的整个环境中仅存在一个实例,比如构建线程池的线程工厂、配置文件的管理器、数据库连接池的管理器等等,在这些场景下,一般为了节省内存或保证原子语义,只需要在环境中构建一个实例即可,单例模式(singleton pattern)就是为了实现单例的一种代码设计模式。
Java代码如何实现?
//饿汉式单例
//优点:①简单实用;②JVM保证线程安全(同一类只会加载一次)
//缺点:无论使用与否,类加载时就已经完成了实例化,占用内存
public class Mgr01{
//1.定义一个final的静态属性
private static final Mgr01 INSTANCE = new Mgr01();
//2.将构造方法私有化
private Mgr01(){}
//3.提供一个获取实例的静态方法
public static Mgr01 getInstance(){
return INSTANCE;
}
}
//饿汉式单例:与Mgr01一样
public class Mgr02{
//1.定义一个final的静态实例
private static final Mgr02 INSTANCE;
//2.将实例的初始化延迟
static{
INSTANCE = new Mgr02();
}
//3.将构造方法私有化
private Mgr02(){}
//4.提供一个获取实例的静态方法
public static Mgr02 getInstance(){
return INSTANCE;
}
}
//懒汉式单例
//优点:解决饿汉式缺失懒加载的问题
//缺点:引入了线程不安全问题(在判断null时,一个线程判断了但没有执行new,其他线程判断了也执行了new,但第一个线程还是会执行new,最终导致获取的实例并不是单例)
public class Mgr03{
//1.定义一个的静态属性(这里不能使用final,因为final修饰的类属性必须马上初始化)
private static Mgr03 INSTANCE;
//2.将构造方法私有化
private Mgr03(){}
//3.提供一个获取静态实例的静态方法
public static Mgr03 getInstance(){
//4.获取时检查实例是否已经完成初始化
if(null == INSTANCE){
INSTANCE = new Mgr03();
}
return INSTANCE;
}
}
//加锁懒汉式单例
//优点:通过synchronized加锁解决了懒汉式单例的线程不安全问题
//缺点:效率相对较低,因为每一次访问都会加解锁
public class Mgr04{
//1.定义一个静态属性
private static Mgr04 INSTANCE;
//2.构造器私有化
private Mgr04(){}
//3.提供一个获取实例的静态方法
public static synchronized Mgr04 getInstance(){
if(null == INSTANCE){
INSTANCE = new Mgr04();
}
return INSTANCE;
}
}
//锁细化懒汉式单例
//优点:缩小锁的粒度
//缺点:并不能实现单例(已经将null判断与new分离)
public class Mgr05{
//1.定义一个静态属性
private static Mgr05 INSTANCE;
//2.构造器私有化
private Mgr05(){}
//3.提供一个获取实例的静态方法
public static Mgr05 getInstance(){
if(null == INSTANCE){
synchronized(Mgr05.class){
INSTANCE = new Mgr05();
}
}
return INSTANCE;
}
}
//双重检查懒汉式单例(DCL)
//优点:缩小了锁的粒度
//缺点:写法较为复杂,实现缺失优雅
public class Mgr06{
//1.定义一个静态属性(使用volatile禁止指令重排,防止未初始化就返回)
private static volatile Mgr05 INSTANCE;
//2.构造器私有化
private Mgr06(){}
//3.提供一个获取实例的静态方法
public static Mgr06 getInstance(){
if(null == INSTANCE){
synchronized(Mgr06.class){
if(null == INSTANCE){
INSTANCE = new Mgr04();
}
}
}
return INSTANCE;
}
}
//内部类式单例:
//优点:懒加载且线程安全(JVM保证同一个类只会加载一次)
//缺点:暂无
public class Mgr07{
//1.构造方法私有化
private Mgr07(){}
//2.私有静态内部类:静态内部类只有在用到时才会被初始化
private static class Mgr07Inner{
private final static Mgr07 INSTANCE = new Mgr07();
}
//3.提供一个获取单例的静态方法
public static Mgr07 getInstance(){
return Mgr07Inner.INSTANCE;
}
}
//枚举式单例
//优点:简单且防止住了反序列化
//缺点:优点违背枚举的语义,一般很少在枚举中写业务方法
public enum Mgr08{
INSTANCE;
}
版权声明:本文为weixin_43647393原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。