单例怎么写( 二 )


if(a==null){
return new A();
}
return a;
}
}
//饿汉式
public class A{
public static synchonized A a = new A();//线程安全
public A(){
}
public A getInstance(){
return a;
}
}
所谓饿就是急 , 无论需不需要先将单例对象给创建了 , 而懒汉式就是慢 , 需要的时候再创建 , 此外还有利用java缓存式的 , 利用内部类实现的单例模式 , 具体可以参考《清华大学出版社》出版的《研磨设计模式》
4. 如何写一个简单的单例模式 单例模式的要点有三个;一是某各类只能有一个实例;二是它必须自行创建这个事例;三是它必须自行向整个系统提供这个实例 。
单例模式有以下的特点:
1 单例类只可有一个实例 。
2 单例类必须自己创建自己这惟一的实例 。
3 单例类必须给所有其他对象提供这一实例 。
public class EagerSingleton
{
private static final EagerSingleton m_instance =
new EagerSingleton();
/**
* 私有的默认构造子
*/
private EagerSingleton() { }
/**
* 静态工厂方法
*/
public static EagerSingleton getInstance()
{
return m_instance;
}
}
在这个类被加载时 , 静态变量m_instance 会被初始化 , 此时类的私有构造子会被调用 。这时候 , 单例类的惟一实例就被创建出来了 。
楼主可以具体参阅 阎宏博士的《Java与模式》一书的第十五章
5. 如何正确地写出单例模式 当被问到要实现一个单例模式时 , 很多人的第一反应是写出如下的代码 , 包括教科书上也是这样教我们的 。
1234567891011public class Singleton {private static Singleton instance;private Singleton (){}public static Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}}这段代码简单明了 , 而且使用了懒加载模式 , 但是却存在致命的问题 。当有多个线程并行调用 getInstance() 的时候 , 就会创建多个实例 。
也就是说在多线程下不能正常工作 。懒汉式 , 线程安全为了解决上面的问题 , 最简单的方法是将整个 getInstance() 方法设为同步(synchronized) 。
123456public static synchronized Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}虽然做到了线程安全 , 并且解决了多实例的问题 , 但是它并不高效 。因为在任何时候只能有一个线程调用 getInstance() 方法 。
但是同步操作只需要在第一次调用时才被需要 , 即第一次创建单例实例对象时 。这就引出了双重检验锁 。
双重检验锁双重检验锁模式(double checked locking pattern) , 是一种使用同步块加锁的方法 。程序员称其为双重检查锁 , 因为会有两次检查 instance == null  , 一次是在同步块外 , 一次是在同步块内 。
为什么在同步块内还要再检验一次?因为可能会有多个线程一起进入同步块外的 if , 如果在同步块内不进行二次检验的话就会生成多个实例了 。12345678910public static Singleton getSingleton () {if (instance == null ) { //Single Checkedsynchronized (Singleton.class) {if (instance == null ) { //Double Checkedinstance = new Singleton();}}}return instance ;}这段代码看起来很完美 , 很可惜 , 它是有问题 。
主要在于 instance = new Singleton() 这句 , 这并非是一个原子操作 , 事实上在 JVM 中这句话大概做了下面 3 件事情 。给 instance 分配内存调用 Singleton 的构造函数来初始化成员变量将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)但是在 JVM 的即时编译器中存在指令重排序的优化 。