什么是单例?为什么需要单例?
这真TMD枯燥!!!老子不想看? 嗯,对, 你完全可以不看这一段,但是推荐看下代码里面的注释!
许多时候整个系统只需要拥有一个的全局对象这样有利于我们协调系统整体的行为。比如在某个服务器")程序中,该服务器的配置信息存放在一个[文件]中,这些配置数据由一个单例对象统一读取,然后服务[进程]中的其他对象再通过这个单例对象获取这些配置信息,常见的Windows系统的任务管理器也是到哪里模式;
实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;
单例的五种实现
- 静态内部类实现,推荐用法:支持懒加载,高效的线程安全;常用于大型框架中;
class Singleton{
//静态内部类
private Singleton(){}
/**
* 静态内部类在Singleton.class加载的时候是不会加载的,所以是懒加载;另外当调用getInstance()方法
* 的时候,JVM会加载内部类;而 jvm加载类的时候本身就是线程安全的,不加同步锁,所以相对高效
*/
private static class SingleInnerCls{
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingleInnerCls.instance ;
}
}
哎吆,我赶脚分不清懒汉方式, 饿汉方式?
根据单例对象的生成时间,逼脸,哦不!比懒?
显然,懒汉模式是在初次调用对象的时候new的对象,而饿汉模式类加载的时候就new了对象;
- 懒汉方式,特点:支持懒加载,多线程获取单例对象效率相对低;
class Singleton{
//静态内部类
private Singleton(){}
//静态对象
private static Singleton instance;
//加上同步锁,导致多线程调用时效率降低
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
- 饿汉方式,特点:不支持懒加载,但是没有同步锁,多线程获取单例对象效率相对高;
class Singleton{
//静态内部类
private Singleton(){}
//饿汉一生下来就有了对象,真他娘的幸福!
//即便是没有用到这个对象,jvm也会提供
private static Singleton instance = new Singleton();
//不用同步锁
public static Singleton getInstance(){
return instance;
}
}
剩下两个不怎么入流,但是你我绝不是浅尝辄止的人![装逼击掌]
- 通过枚举实现单例,特点:先天的线程单例,线程安全, 但无延时加载
enum SinglettonEnum{
Instance;
//枚举元素的操作方法
public void otherOpera() {
System.out.println("其他操作...");
}
}
- 双重检测锁实现单例,特点:听这名字感觉是个王者,实则是个不推荐使用的黑铁!!! 因为jvm底层的原因,会偶尔出现问题。跟懒汉模式相比,他把锁放在了方法里面,多线程调用方法无需等待,只是初始化对象的时候要等待一次。
class SinglettonDoubleCheck{
private SinglettonDoubleCheck(){}
private static SinglettonDoubleCheck instance;
public static SinglettonDoubleCheck GetInstance() {
if(instance == null){
synchronized(SinglettonDoubleCheck.instance){
if(instance == null) {
instance = new SinglettonDoubleCheck();
}
}
}
return instance;
}
}