设计模式 单例模式轻谈

单例模式

使用率最高的设计模式,使用单例模式的类必须保证在整个进程中只会创建该类的1个对象,它属于创造性模式!

 

优点

1、节省内存空间

2、减少性能开销

 

缺点

1、可能引起内存泄漏

2、扩展性差

 

代码关键点

1、private修饰构造方法,表示不允许其他人通过构造方法创建对象

2、private修饰一个static变量,static变量负责持有创建的唯一的单例对象(单例类持有单例对象)

3、public修饰的static方法返回唯一创建的单例对象

4、确保多线程下可使用单例对象

5、确保反序列化时不会创建新的对象

 

第一种方式(饿汉模式):定义static变量时,同时立即创建单例对象

缺点:类加载到JVM内存中时,立刻创建了单例对象,影响类加载到JVM内存时的性能

优点:线程安全(依赖类加载机制)

说明:这种写法常被称为饿汉模式,the singleton instance is early created at complie time中的early直接音译过来的,因为对象创建的时机非常的早……不知道是谁这么翻译的……音译……还是表示特别的饿……

public class SingleTest {

		private SingleTest() {
			super();
			System.out.println("SingleTest()");
		}

		private static SingleTest Instance = new SingleTest();

		public static SingleTest getInstance() {
			System.out.println("getInstance()");
			return Instance;
		}

		public static void main(String args[]) {
			SingleTest sTest = getInstance();
		}

	}

 

第二种方式(懒汉模式)

    定义static变量负责持有单例对象(类负责持有单例对象),单例对象则延迟在静态方法被调用时创建

缺点:不支持多个线程同时调用创建对象的静态方法getInstance(),非线程安全

优点:调用静态方法时才会创建单例对象,实现了懒加载,保证了类加载JVM时的加载效率

说明:这种方式常被称为懒汉模式,the singleton instance is lazily created at runtime中的lazily的音译,因为对象创建的比较晚!这翻译太糟糕……而且还传开了……

public class SecSingle {
	private static SecSingle instance;
	
	private SecSingle(){
		super();
	}
	
	public static SecSingle getInstance() {
		if (instance == null) {
			instance = new SecSingle();
		}
		return instance;
	}
}

 

第三种方式(同饿汉模式)

    类加载到JVM时,在静态代码块中创建单例对象

缺点:类加载到JVM内存时创建了对象,影响类加载到JVM内存中的性能

优点:线程安全

说明:同本文第一种方式完全一样,只是写法不同而已……,staitc语句最终都会在JVM生成的一个类构造器方法<clinit>中执行的

class ThirdSingleton {
	private static ThirdSingleton instance;
	
	private ThirdSingleton(){
	}
	
	static {
		instance = new ThirdSingleton();
	}
	
	public static ThirdSingleton getInstance(){
		return instance;
	}
}

 

第四种方式(同饿汉模式)

缺点:类加载时即创建对象,影响类加载到JVM内存中的性能

优点:线程安全

说明:同本文第一种方式,只不过static变量由final修饰……

class FourthSingleton {
	private final static FourthSingleton mInstance = new FourthSingleton();
	
	private FourthSingleton(){
		
	}
	
	public static FourthSingleton getInstance() {
		return mInstance;
	}
}

 

第五种方式

    同步静态方法调用时创建单例对象

缺点:静态方法使用synchronized修饰,当单例对象已经创建,其它的线程仍然需要再次持有对象锁(Class对象的锁)后才能访问该静态方法,线程获取锁与释放锁会影响运行效率

优点:线程安全

说明:不推荐使用该方式,静态方法被调用时,需要获取与释放对象锁,影响性能

class FifthSingleton {
	private static FifthSingleton mInstance;
	
	private FifthSingleton(){
		super();
	}
	
	public static synchronized FifthSingleton getInstance(){
		if(mInstance == null){
			mInstance = new FifthSingleton();
		}
		
		return mInstance;
	}
}

 

第六种方式

    静态方法调用时创建单例对象

缺点:线程不安全,因同步代码块的范围加的不正确,2个线程有可能已经同时进入if(mInstance == null)的代码块,此时会造成每个线程都去创建一个对象

优点:懒加载,对象创建时机晚,使用时创建的对象

class SixthSingleton {
	private static SixthSingleton mInstance;
	
	private SixthSingleton(){
		super();
	}
	
	public static SixthSingleton getInstance(){
		if(mInstance == null) {
			synchronized (SixthSingleton.class) {
				mInstance = new SixthSingleton();
			}
		}
		return mInstance;
	}
}

 

第七种方式

    采用双重校验锁的静态方法创建单例对象(Double Check Lock,DCL)

缺点:相对来说已经无缺点(推荐使用)

优点:线程安全(推荐使用),传说中的双重校验锁方式,弥补了第六种方式的bug,只有对象未创建时线程才会持有对象锁,当线程持有对象锁后,会在同步代码块中继续判断对象是否已经创建?未创建的情况才会创建对象,这样即确保线程安全,又确保效率第一(线程不必每次访问该静态方法都持有对象锁)

class SeventhSingleton {
	private static SeventhSingleton mInstance;
	
	private SeventhSingleton(){
		
	}
	
	public static SeventhSingleton getInstance(){
		if(mInstance == null) {
			synchronized (SeventhSingleton.class) {
				if(mInstance == null) {
					mInstance = new SeventhSingleton();
				}
			}
		}
		return mInstance;
	}
}

 

第八种方式

    静态内部类加载到JVM时创建单例对象

缺点:无明显的缺点(推荐使用)

优点:线程安全,利用类加载机制确保线程安全,又利用使用单例对象时才加载到JVM内存中,即保证线程安全,又保证类加载到JVM内存中的效率,牛逼!

class EighthSingleton {
	private EighthSingleton(){
		super();
	}
	
	private static class Single {
		private static final EighthSingleton INSTACE = new EighthSingleton();
	}
	
	public static EighthSingleton getInstance(){
		return Single.INSTACE;
	}
}

 

第九种方式

    利用HashMap对象持有多个单例对象!等待…………

…………

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值