java性能优化--代理--单例

单例模式是一种对象建立模式,用于生产对象的一个具体实例,它能够确保系统中一个类只产生一个实例。该模式能带来两大好处: java

    1. 对于频繁使用的对象,能够省略建立对象所花费的时间。 多线程

    2. 因为new的次数减小,于是对系统内存的使用频率也会下降,这将减轻GC压力、缩短gc停顿时间 函数

单例模式的核心,在于经过一个接口返回惟一的对象实例。一个简单的单例实现: 工具


public class Singleton {
	private Singleton(){
		System.out.println("create a Singleton");
	}
	
	private static Singleton instance = new Singleton();

	public static Singleton getInstance(){ return instance;
	}
}
  首先,单例必须有一个private访问级别的构造函数,只有这样,才能确保单例不会在系统中的其余代码内被实例化;其次,instance成员变量和getInstance()的方法必须是static的



这种实现方式很简单而且仍是十分可靠的,它惟一的不足就是没法对instance进行延迟加载,实现延迟的代码为 性能

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;
	}
}
首先,对于静态变量instance初始值赋予null,确保系统启动时没有额外的负载;
其次,get方法必须是同步的,不然在多线程请扩下,可能会屡次建立!
可是因为引入了同步,其性能会和第一种状况差了不少,因此这种下降了系统性能的作法,是有点不可取的,因此咱们对其进行改进:
public class StaticSingleton {


 private StaticSingleton(){
 System.out.println("create a StaticSingleton");
 }
 
 private static class SingletonHolder{
 private static StaticSingleton instance = new StaticSingleton();
 }
 
 public static StaticSingleton getInstance(){
 return SingletonHolder.instance;
 }
}
这个实现中,单例模式使用内部类来维护实例,当StaticSingleton被加载时,其内部类不会初始化,故能够在调用getInstance()方法调用,才会加载SingletonHolder.同时,因为实例的创建实在类加载时完成,故天生对多线程友好
一般状况下上面的代码能够确保系统中惟一实例。可是仍有意外状况,好比利用反射,这种状况咱们不讨论,咱们讨论一种合理的方法:
public class SerSingleton implements Serializable {


 String name;
 private SerSingleton(){
 System.out.println("create a SerSingleton");
 name = "SerSingleton";
 }
 
 private static SerSingleton instance = new SerSingleton();
 public static SerSingleton getInstance(){
 return instance;
 }
 
 public static void createString(){
 System.out.println("createString in Singleton");
 }
 
//	private Object readResolve(){
//		return instance;
//	}
}
// TODO Auto-generated method stub
 SerSingleton s1 = null;
 SerSingleton s  = SerSingleton.getInstance();
 //先将实例串行化到文件
 FileOutputStream fos = new FileOutputStream("s.txt");
 ObjectOutputStream oos = new ObjectOutputStream(fos);
 oos.writeObject(s);
 oos.flush();
 oos.close();
 
 //从文件读出
 FileInputStream fis = new FileInputStream("s.txt");
 ObjectInputStream ois = new ObjectInputStream(fis);
 s1= (SerSingleton) ois.readObject();
//		Assert.assertEquals(s,s1);
 System.out.println(s.equals(s1));
若是在第一段代码中去掉readResovle(),那么测试代码(通过串行化和反串行化)后,s和s1指向了不一样的实例;加上以后便解决该问题。
即便构造函数是私有的,可序列化工具依然能够经过特殊的途径去建立类的一个新的实例。序列化操做提供了一个很特别的钩子(hook)-类中具备一个私有的被实例化的方法readresolve(),这个方法能够确保类的开发人员在序列化将会返回怎样的object上具备发言权。足够奇怪的,readresolve()并非静态的,可是在序列化建立实例的时候被引用。
相关文章
相关标签/搜索