主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
?
# 是否多线程安全:是;它基于 classloader 机制避免了多线程的同步问题
# 其他描述:
这种方式比较常用,但容易产生垃圾对象。
- 优点:没有加锁,执行效率会提高。
- 缺点:类加载时就初始化,浪费内存。
public class Singleton{
//在类加载时就会初始化静态变量实例
private static Singleton instance = new Singleton();
// 构造方法私有,确保外界不能直接实例化
private Singleton(){}
//通过公有的静态方法获取实例对象
public static Singleton getInstance(){
return instance;
}
}
# 是否多线程安全:否;因为没有加锁 synchronized
# 其他描述:
这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程,不要求线程安全,在多线程不能正常工作。
public class Singleton {
//先置空,在调用的时候实例化对象
private static Singleton instance = null;
// 私有构造方法,确保外界不能直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
public static Singleton getInstace() {
if (instance == null) {
instance = new Singleton(); }
return instance;
}
}
如果线程A和B同时调用此方法,会出现执行if (instance == null)
语句时都为真的情况,那么线程A和B都会创建一个对象,那内存中就会出现两个对象,这违反了单例模式的定义。
为解决这一问题,使用synchronized
关键字对静态方法 getInstance()
进行同步,防止多线程同时进入造成 instance 被多次实例化。
# 是否多线程安全:是;因有加锁 synchronized
# 其他描述:
这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。
public class Singleton {
private static Singleton instance = null;
// 私有构造方法,确保外界不能直接实例化。
private Singleton() {}
// 通过公有的静态方法获取对象实例
synchronized public static Singleton getInstace() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
资源利用效率:饿汉式<懒汉式;
速度和反应上:饿汉式>懒汉式;