什么是单例模式
单例模式是一种对象创建模式,用来确保系统中一个类只产生一个实例
为什么要使用单例模式
- 对于频繁使用的对象,可以省略创建对象的时间
- 创建对象的动作减少,对系统内存的使用频率会降低,这将减轻GC的压力
单例模式怎么写
package singleton;
/**
* @author xiaotudou
*/
public class Singleton {
private Singleton(){
System.out.println("Singleton is create");
}
private static Singleton instance=new Singleton();
public static Singleton getInstance(){
return instance;
}
}
重点:
- 构造方法要私有。可以确保程序其他位置无法通过new创建实例对象。保证了实例的单一
public static Singleton getInstance()
要使用静态方法返回单一的实例。因为静态方法不需要对象实例调用
缺点:
- 无法延迟加载。根源在于
private static Singleton instance=new Singleton();
静态对象在类加载的时候创建。即使程序中没有使用到这个对象,但是在类加载的时候,对象还是创建了。这对资源是一种浪费。
改进:
package singleton;
/**
* @author Liudj
*/
public class LazySingleton {
private LazySingleton(){
System.out.println("LazySingleton is created");
}
private static LazySingleton lazySingleton=null;
/**
* 必须是同步的,否则在多线程情况下,有可能创建多个实例
* @return
*/
public static synchronized LazySingleton getInstance(){
if(lazySingleton==null){
lazySingleton=new LazySingleton();
}
return lazySingleton;
}
}
重点:
public static synchronized LazySingleton getInstance()
返回实例的方法必须是同步的。因为在多线程场景中。第一个线程发现lazySingleton为null。创建实例对象。在对象创建完成之前。第二个线程访问lazySingleton仍然是null。所以会重复创建对象。虽然最终结果没有影响。但是多次创建对象浪费系统资源,违背单例模式的设计思想。
缺点:
- 同步关键字保证了对象只创建一次。但是在多线程环境中,同步关键字十分的耗费时间
改进:
package singleton;
/**
* @author Liudj
*/
public class StaticSingleton {
private StaticSingleton(){
System.out.println("StaticSingleton is create");
}
private static class SingletonHolder{
private static StaticSingleton staticSingleton=new StaticSingleton();
}
public static StaticSingleton getInstance(){
return SingletonHolder.staticSingleton;
}
}
重点:
- 使用静态内部类创建实例对象
优点说明:
内部类中创建对象。当单例类中其他方法被调用时,单例类被加载时并不会导致内部类被初始化。做到了延迟加载。当调用getInstance方法时,进行对象的初始化,而对象初始化是在类加载时被创建的,所以天生对多线程友好。因此这种方式同时具备以上两种实现的优点。