单例模式
2018-06-26 本文已影响0人
昼暗
背景
系统中一个类只产生一个实例,好处
- 可以省略创建对象所花费的时间
- new操作减少, 因而系统内存的使用频率也会降低, 将减轻GC的压力
代码
- 缺点: 此时我们没有真正使用单例类, 但是单例类还是被创建了.所以我们希望可以延迟加载
public class Singleton {
private Singleton(){
System.out.println("Singleton is create");
}
private static Singleton instance = new Singleton();
public static Singleton getInstance () {
return instance;
}
public static void createString(){
System.out.println("createString in Singleton");
}
}
- 改进
缺少: 可以实现延迟加载 但是使用了同步关键字会降低性能
public class LazySingleton {
private LazySingleton(){
System.out.println("LazySingleton is create");
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance(){
if(instance==null)
instance = new LazySingleton();
return instance;
}
}
- 继续改进
StaticSingleton加载时内部类不会被初始化
当getInstance被调用时, 才会加载内部类,从而初始化instance,
由于实例的建立实在类加载时完成,所以对多线程友好
public class StaticSingleton {
private StaticSingleton() {
System.out.println("StaticSingleton is create");
}
private static class SingletonHolder{
private static StaticSingleton instance = new StaticSingleton();
}
public static StaticSingleton getInstance(){
return SingletonHolder.instance;
}
}
- 通常情况下, 以上基本可以确保系统中只存在唯一实例. 但仍有合法的方法, 可能导致系统中出现多个实例
public class SerSingleton implements Serializable{
String name;
private SerSingleton(){
System.out.println("SerSingleton is create");
name = "SerSingleton";
}
private static SerSingleton instance = new SerSingleton();
public static SerSingleton getInstance (){
return instance;
}
public static void createString(){
System.out.println("createString in Singleton");
}
// 可以防止反序列化时 生成新的实例
// 方法注释掉的化, 会输出false
private Object readResolve(){
return instance;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
SerSingleton s1 = null;
//对象序列化
SerSingleton s = SerSingleton.getInstance();
FileOutputStream fos = new FileOutputStream("SerSingleton.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s);
oos.flush();
oos.close();
// 反序列化
FileInputStream fis = new FileInputStream("SerSingleton.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
s1 = (SerSingleton)ois.readObject();
System.out.println(s == s1);
}
}