单例模式
定义: 对象创建模式,确保系统中一个类只产生一个实例
使用单例的好处:
1): 对频繁使用的对象,省略创建对象所花费的时间
2):new 操作次数的减少,对系统内存的使用频率也会降低,减轻GC压力,缩短GC停顿时间。
创建单例模式
第一种方式):类一加载就创建
public class Singleton {
/**
私有化构造方法,外界不能通过new运算符创建对象
*/
private Singleton(){
System.out.println("create singleton");
}
/**
* 实例化Singleton对象,static修饰,在类加载时实例化
*/
private static Singleton instance = new Singleton();
/**
* 提供一个接口,外界可以通过该接口获取Singleton对象
*/
public static Singleton getInstance(){
return instance;
}
}
弊端:在使用单例类时,不管有没有使用单例对象,单例变量都会通过new运算符实例化。
public class Singleton {
/**
私有化构造方法,外界不能通过new运算符创建对象
*/
private Singleton(){
System.out.println("create singleton");
}
/**
* 实例化Singleton对象,static修饰,在类加载时实例化
*/
private static Singleton instance = new Singleton();
/**
* 提供一个接口,外界可以通过该接口获取Singleton对象
*/
public static Singleton getInstance(){
return instance;
}
public static void getString(){
System.out.println("ceateString in Singleton");
}
}
//执行Singleton.getString()程序输出
create singleton
ceateString in Singleton
//不管有没有使用单例对象,单例变量都会通过new运算符实例化
第二种方式):延迟加载
先将单例变量声明为null,只有使用单例对象时,才通过new运算符创建实例
public class LazySingleton {
/**
声明私有的构造器
*/
private LazySingleton(){
System.out.println("create lazySingleton");
}
/**
* 单例变量初始化时不进行实例化
*/
private static LazySingleton instance = null;
/**
* 1)提供获取单例对象的接口
* 2)加锁:
* 防止线程1在未赋值前,线程2可能判断instance == null,此时会产生两个单例对象
* @return
*/
public static synchronized LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
弊端:多线程调用时可能会产生两个单例对象,使用了sychonized可以预防该现象出现,但时耗远远大于第一种模式
第三种方式):使用私有的静态成员内部类的方式
public class StaticSingleton {
/**
* 将构造方法私有化
*/
private StaticSingleton(){
System.out.println("create staticSingleton");
}
/**
* 创建静态成员内部类,在内部类中创建单例对象
* --:静态成员内部类在外部类加载时不会加载,只有在调用时才会加载
*/
private static class SingletonHolder{
private static StaticSingleton instance = new StaticSingleton();
}
/**
* 提供获取单例的接口
* ---:满足了只有在使用单例时才使用new进行实例化,也不必使用synchonized关键字
*/
public static StaticSingleton getInstance(){
return SingletonHolder.instance;
}
public static void get(){
System.out.println("get");
}
}
好处:解决了延迟加载的问题,单例可以在使用时创建,也不必使用synchonized关键字