1.单例模式定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例(Ensure a class has only one instance, and provide a global point of access to it).
2.单例模式好处:对于需要频繁创建和销毁的对象使用单例模式可以节省开销,对于重量级对象而言性能十分明显。减轻GC的压力,从而缩短GC停顿时间。
3. 单例模式通用代码
public class Singleton {
private static Singleton singleton=new Singleton();
private Singleton(){}
public static Singleton getSingleton()
{
return singleton;
}
public static void doSometing(){} //类中其他方法尽量使static
}
4.单例模式使用场景和注意事项
适用于要求生成唯一序列号的环境或整个项目中需要一个共享访问点。单例模式在高并发情况下,由于对象初始化需要时间,所以当一个线程尚未初始化完毕的时候,另一个线程也会进行初始化,所以便产生了多个对象。
5.单例模式优化
(1).调用时创建。对于上述通用的创建方法,在虚拟机加载此类的初始化阶段,就会创建此类对象的实例从而产生一定的负载,为了减少类初始化时候的时间可以在调用的时候再调用构造器。
public class Singleton {
private static Singleton singleton=null; //初始化阶段赋Null 所以不会进行实例化
private Singleton(){}
public static Singleton getSingleton() //当发生调用的时候才会实例化。
{
if(singleton==null)
{
singleton=new Singleton();
}
return singleton;
}
public static void doSometing(){}
}
(2). 并发下同步。由于单例模式并不是线程安全的所以在多并发情况下对其同步变得十分必要
通过不变量保证线程安全。
public class Singleton {
private static final Singleton singleton=new Singleton();
//将产生的实例设置为不变量,并在JVM加载的时候进行初始化。
private Singleton(){}
public static Singleton getSingleton()
{
return singleton;
}
public static void doSometing(){}
}
使用synchronized关键字。由于使用同步关键字是重量级的同步所以对性能将产生很大的影响。
public class Singleton {
private static Singleton singleton=null;
private Singleton(){}
public static synchronized Singleton getSingleton() //使用同步关键字进行方法级同步
{
if(singleton==null)
{
singleton=new Singleton();
}
return singleton;
}
public static void doSometing(){}
}
通过内部类来同步。内部类由于在JVM加载类的时候才初始化实例,所以天生多线程友好,同时又保持了调用时实例化的特性。
public class Singleton {
private static Singleton singleton=null;
private Singleton(){}
//内部类在发生调用的时候才开始加载并且在加载的时候就进行一次初始化所以线程安全。
private static class SingletonHolder{private static Singleton instance =new Singleton();}
public static Singleton getSingleton()
{
return SingletonHolder.instance;
}
public static void doSometing(){}
}
6.注意
单例模式依然有许多会被破坏的情况 如:通过反射调用私有构造函数,单例的串行化和反串行化等。
单例模式会与单一职责原则有冲突。具体是否使用单例要看项目所处的环境和目标。