//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
//私有的构造函数
private Singleton() {}
//私有的静态变量
private static Singleton single=null;
//暴露的公有静态方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
public class Singleton {
//私有的静态变量
private static Singleton instance;
//私有的构造方法
private Singleton (){};
//公有的同步静态方法
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton {
//static修饰的静态变量在内存中一旦创建,便永久存在
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
static {
instance = new Singleton();
}
public class Singleton {
private static Singleton singleton; //静态变量
private Singleton (){} //私有构造函数
public static Singleton getInstance() {
if (singleton == null) { //第一层校验
synchronized (Singleton.class) {
if (singleton == null) { //第二层校验
singl
eton = new Singleton();
}
}
}
return singleton;
}
}
具体我们来分析一下: 假设线程A执行到了singleton = new Singleton(); 语句,这里看起来是一句代码,但是它并不是一个原子操作,这句代码最终会被编译成多条汇编指令,它大致会做三件事情:
但是在JDK1.5之后,官方给出了volatile关键字,将singleton定义的代码,为了解决DCL失效的问题。
private volatile static Singleton singleton; //使用volatile 关键字
public class Singleton {
private Singleton (){} ;//私有的构造函数
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
//定义的静态内部类
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton(); //创建实例的地方
}
}
前面的几种单例模式实现方式,一般都会稍显麻烦,或是在某些特定的情况下出现一些状况。下面介绍枚举单例模式的实现:
public enum Singleton { //enum枚举类
INSTANCE;
public void whateverMethod() {
}
}
枚举单例模式最大的优点就是写法简单,枚举在java中与普通的类是一样的,不仅能够有字段,还能够有自己的方法,最重要的是默认枚举实例是线程安全的,并且在任何情况下,它都是一个单例。即使是在反序列化的过程,枚举单例也不会重新生成新的实例。而其他几种方式,必须加入如下方法:
private Object readResolve() throws ObjectStreamException{
return INSTANCE;
}
这样的话,才能保证反序列化时不会生成新的方法
public class SingletonManager {
private static Map<String, Object> objMap = new HashMap<String,Object>();//使用HashMap作为缓存容器
private Singleton() {
}
public static void registerService(String key, Objectinstance) {
if (!objMap.containsKey(key) ) {
objMap.put(key, instance) ;//第一次是存入Map
}
}
public static ObjectgetService(String key) {
return objMap.get(key) ;//返回与key相对应的对象
}
}
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
这样的话它的资源利用率会很高,并且第一次执行的时候,是单例对象才会被实例化,但是第一次加载的时候会稍慢,可以被接受
LayoutInflater mInflater = LayoutInflater.from(this);
上边的写法估计没有人会陌生,获取LayoutInflater 的实例,我们一起看看具体的源码实现:
/**
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
/**
Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
到这里了相信各位已经感觉这是上述说的使用容器实现单例模式了,对比一下,果然是
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
/**
static {
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
new CachedServiceFetcher() {
@Override
public LayoutInflater createService(ContextImpl ctx) {
return new PhoneLayoutInflater(ctx.getOuterContext());
}});
}
注册的
static {
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
new CachedServiceFetcher() {
@Override
public LayoutInflater createService(ContextImpl ctx) {
return new PhoneLayoutInflater(ctx.getOuterContext());
}});
}