翻译自:http://blog.csdn.net/dmk877/article/details/50311791
/**
* Created by admin on 2016/8/24.
*/
public class Singleton {
//饿汉模式
/**
* 1 类加载时初始化 内存浪费但可忽略,可以使用
*/
/*private static Singleton instance = new Singleton();
private Singleton(){};
public static Singleton getInstance(){
return instance;
}*/
/**
* 2 饿汉式变换写法[可用]
*/
/*private static Singleton instance = null;
static{
instance = new Singleton();
}
private Singleton(){};
public Singleton getInstance(){
return instance;
}*/
//懒汉模式
/**
* 1 线程不安全,不可用
* 这种方式是在调用getInstance方法的时候才创建对象的,所以它比较懒因此被称为懒汉式。
* 在上述两种写法中懒汉式其实是存在线程安全问题的,喜欢刨根问题的同学可能会问,存在怎
* 样的线程安全问题?怎样导致这种问题的?好,我们来说一下什么情况下这种写法会有问题。
* 在运行过程中可能存在这么一种情况:有多个线程去调用getInstance方法来获取Singleton
* 的实例,那么就有可能发生这样一种情况当第一个线程在执行if(instance==null)这个语句
* 时,此时instance是为null的进入语句。在还没有执行instance=new Singleton()时(
* 此时instance是为null的)第二个线程也进入if(instance==null)这个语句,因为之前进
* 入这个语句的线程中还没有执行instance=new Singleton(),所以它会执行instance=
* new Singleton()来实例化Singleton对象,因为第二个线程也进入了if语句所以它也会实
* 例化Singleton对象。这样就导致了实例化了两个Singleton对象。所以单例模式的懒汉式是
* 存在线程安全问题的
*/
/*private static Singleton instance = null;
private Singleton(){};
public static Singleton getInstance(){
if(null==instance){
instance = new Singleton();
}
return instance;
}*/
/**
* 2
* 同上,线程不安全,当一个线程还没有实例化Singleton时另一个线程执行到if(instance==null)
* 这个判断语句时就会进入if语句,虽然加了锁,但是等到第一个线程执行完instance=
* new Singleton()跳出这个锁时,另一个进入if语句的线程同样会实例化另外一个Singleton对象,
* 线程不安全的原理同上。
*/
/*private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(null==instance){
synchronized(Singleton.class){
instance = new Singleton();
}
}
return instance;
}*/
/**
* 3 线程安全,效率低,不推荐使用
* 效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。
* 而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了
*/
/*private static Singleton instance;
private Singleton(){};
public static synchronized Singleton getInstance(){
if(null==instance){
instance = new Singleton();
}
return instance;
}*/
/**
* 4 双重校验锁[推荐用]
* Double-Check概念对于多线程开发者来说不会陌生,如代码中所示,我们进行了两次
* if (instance== null)检查,这样就可以保 证线程安全了。这样,实例化代码
* 只用执行一次,后面再次访问时,判断if (instance== null),直接return实例化
* 对象。
* 优点:线程安全;延迟加载;效率较高。
*/
/*private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(null==instance){
synchronized (Singleton.class){
if(null==instance){
instance = new Singleton();
}
}
}
return instance;
}*/
//内部类 可以使用
/**
* 这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制
* 来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要Singleton类
* 被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类
* 被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会
* 装载SingletonHolder类,从而完成Singleton的实例化。类的静态属性只会在
* 第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类
* 进行初始化时,别的线程是无法进入的。
* 优点:线程安全,延迟加载,效率高。
*/
/*private Singleton(){}
private static class SingletonHolder{
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}*/
//枚举见SingletonEnums, 极简单,JDK1.5推荐使用
/**
* 可以看到枚举的书写非常简单,访问也很简单在这里SingletonEnum.instance这里
* 的instance即为SingletonEnum类型的引用所以得到它就可以调用枚举中的方法了。
* 借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止
* 反序列化重新创建新的对象。可能是因为枚举在JDK1.5中才添加,所以在实际项目开发
* 中,很少见人这么写过,这种方式也是最好的一种方式,如果在开发中JDK满足要求的情
* 况下建议使用这种方式
*/
SingletonEnum e = SingletonEnum.instance;
}
SingletonEnum
/**
* Created by admin on 2016/8/24.
*/
public enum SingletonEnum {
instance;
private SingletonEnum(){}
}