单例模式

1.下面这个例子是工作中常见的单例模式...jdk1.5之后用volatile关键字禁止编译器重排序

package singleton;

public class DoubleCheckSingleton {
    private volatile static DoubleCheckSingleton instance= null;
    private DoubleCheckSingleton(){}
    public static DoubleCheckSingleton getInstance(){
        if(instance == null ) {
            synchronized(DoubleCheckSingleton.class) {
                if(instance==null) {
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}

2.利用静态内部类生成单例,初始化单例在私有内部静态类中,其他线程无法看到初始化的编译器重排序。

package singleton;

public class SingletonByHolder{
    private SingletonByHolder(){};
    public static SingletonByHolder getInstance(){
        return SingletonHolder.instance;
    }
    
    private static class SingletonHolder
    {
        private static SingletonByHolder instance = new SingletonByHolder();
    }
}

3. 1和2的方法无法防止序列化和反序列化时生成不同的实例,如果单例类需要实现序列化的话,改成下面的方法可以预防(参考《Java程序性能优化》

package singleton;

import java.io.Serializable;

public class SingletonByHolder implements Serializable{
    private static final long serialVersionUID = 333332L;
    
    private SingletonByHolder(){};
    public static SingletonByHolder instance;
    
    public static SingletonByHolder getInstance(){
        instance = SingletonHolder.instance;
        return instance;
    }
    
    private static class SingletonHolder
    {
        private static SingletonByHolder instance = new SingletonByHolder();
    }
    
    private Object readResolve(){
        return instance;
    }
}

测试类

package singleton;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException
    {
        SingletonByHolder instance = SingletonByHolder.getInstance();
        FileOutputStream fo = new FileOutputStream("D:\\serSingleton.txt");
        ObjectOutputStream ob = new ObjectOutputStream(fo);
        ob.writeObject(instance);
        ob.flush();
        ob.close();
        fo.close();
        
        FileInputStream fi = new FileInputStream("D:\\serSingleton.txt");
        ObjectInputStream oi = new ObjectInputStream(fi);
        SingletonByHolder instance2 = (SingletonByHolder) oi.readObject();
        oi.close();
        fi.close();
        System.out.println(instance == instance2);
    }
}

如果注释掉private Object readResolve()方法测试类打印false,反序列化后两个实例不是同一个;没注释掉的话打印true,反序列化后两个实例是同一个。

posted @ 2016-06-02 23:10  ~~Cc  阅读(170)  评论(0编辑  收藏  举报