场景分析:
一个类作为公共模块供其他地方调用,而又不想通过不断new对象的方式。因为这种方式会产生大量的实例,加大了不必要的内存消耗。这时候我们需要一个方式,提供一个单一的实例共调用,同时考虑性能和高并发的场景。
1.饿汉模式
public class SingleTon {
/**
* 构造函数私有化,这是必须的
*/
private SingleTon(){};
/**
* 饿汉模式
*/
private static SingleTon instance = new SingleTon();
public static SingleTon getInstance()
{
return instance;
}
}
优点:线程安全,调用快(虽然快不了多少,聊胜于无)
缺点:很明显,不管用没用,实例都被加载了
2.懒汉模式
public class SingleTon {
/**
* 构造函数私有化,这是必须的
*/
private SingleTon(){};
/**
* 懒汉模式
*/
private static SingleTon instance;
public static SingleTon getInstance()
{
if(instance == null)
{
instance = new SingleTon();
}
return instance;
}
}
优点:懒加载,用时才建立实例
缺点:线程不安全,要是对方法加锁
synchronized,又会加大多线程的时候同步的开销
3.DCL(双重检查加锁)
public class SingleTon {
/**
* 构造函数私有化,这是必须的
*/
private SingleTon() {
}
/**
* DCL
*/
private volatile static SingleTon instance;
public static SingleTon getInstance() {
if (instance == null) {
synchronized (SingleTon.class) {
if (instance == null) {
instance = new SingleTon();
}
}
}
return instance;
}
}
优点:线程安全,高并发效率高
缺点: volatile在保证变量原子性的同时,多少有点影响效率。在高并发下可能出错,源于java编译器允许处理器乱序执行(
http://blog.youkuaiyun.com/ns_code/article/details/17348313)
4.静态内部类单例
public class Singleton {
/**
* 构造函数私有化,这是必须的
*/
private Singleton() {
}
/**
* 静态内部类实现单例
*/
private static class InstanceHolder{
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return InstanceHolder.instance;
}
}
原理:静态内部类不随着外部类的装载而装载,只有使用时才会被装载,而且只会被装载一次
优点:目前来看完美解决了高并发
缺点:第一次加载稍微比较慢,个人感觉很细微