(转载)java单例模式的6种写法

第一种(懒汉,线程不安全)
public class Singleton
{
private static Singleton instance;
private Singleton()
{
}

public static Singleton getInstance()
{
if(null == instance)
{
instance = new Singleton();
}
return intance;
}
}
这种写法lazy loading很明显,但致命的是在多线程不能正常工作。


第二种(懒汉,线程安全)
public class Singleton
{
private static Singleton instance;
private Singleton()
{
}

public static synchronized Singleton getInstance()
{
if(null == instance)
{
instance = new Singleton();
}
return intance;
}
}
这种写法能够在多线程中很好的工作,而且看起来它齐备很好的lazy loading,但是效率很低


第三种(饿汉)
public class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
}

public static Singleton getInstance()
{
return intance;
}
}
这种方式基于classloader机制避免了多线程的同步问题,不过instance在类装载时就实例化,没有达到lazy loading的效果。


第四种(静态内部类)
public class Singleton
{
private Singleton()
{
}

public static Singleton getInstance()
{
return SingletonHolder.INSTANCE;
}

priate static class SingletonHolder
{
private static final Singleton INSTANCE = new Singleton();
}
}
这种方式同样利用classloader的机制来保证初始化instance是线程安全的,并且是lazy loading的


第五种(枚举)
public enum Singleton
{
INSTANCE;
public oid whateverMethod()
{
}
}
这种方式是Effectie Java作者Josh Bloch提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化后重新创建新的对象,可谓是很坚强的壁垒。不过1.5才引入的enum特性,用这种方式不免让人觉得生疏。

第六种(双重校验锁)
public class Singleton
{
private volatile static Singleton singleton;
public static Singleton getSingleton()
{
if(singleton == null)
{
synchronized(Singleton.class)
{
if(singleton == null)
{
singleton = new Singleton();
}
}
}
}
return singleton;
}
在JDK1.5之后,该方法才能正常达到单例效果


总结
有两个问题需要注意:
1、如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类装载器,这样的话如果有两个servlet访问一个单例类,他们就都会有各自的实例。

2、如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个该对象,就会有多个单例类的实例

对第一个问题的修复办法是:
private static Class getClass(String classname) throws ClassNotFoundException
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if(null == loader)
{
loader = Singleton.class.getClassLoader();
}
return loader.loadClass(classname);
}

对第二个问题的修复办法是:
public class Singleton implements java.io.Serializable
{
public static Singleton INTANCE = new Singleton();

private Singleton()
{
}

private Object readResolve()
{
return INSTANCE;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值