设计模式--单例模式
单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
1.饿汉式,线程安全 但效率比较低
-
优点是:写起来比较简单,而且不存在多线程同步问题,避免了synchronized所造成的性能问题;
-
缺点是:当类SingletonTest被加载的时候,会初始化static的instance,静态变量被创建并分配内存空间,从这以后,这个static的instance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。
public class HungrySingleton { //定义一个私有构造方法 private HungrySingleton(){ } //将自身的实力对象设置为一个属性,并加上Static和final修饰符 private static final HungrySingleton instance = new HungrySingleton(); //静态方法返回该类的实例 public static HungrySingleton getInstance(){ return instance; } }
2.饱汉式,非线程安全
-
优点是:写起来比较简单,当类SingletonTest被加载的时候,静态变量static的instance未被创建并分配内存空间,当getInstance方法第一次被调用时,初始化instance变量,并分配内存,因此在某些特定条件下会节约了内存;
-
缺点是:并发环境下很可能出现多个SingletonTest实例。
public class SatietySingleton { //定义私有构造方法(防止通过new SatietySingleton()去实例化 private SatietySingleton() { } //定义一个SatietySingleton类型的变量(不初始化,注意这里没有使用final关键字) private static SatietySingleton instance; //定义一个静态的方法(调用时再初始化SatietySingleton,但是多线程访问时,可能造成重复初始化问题) //[考虑线程安全时,将synchronized放开] public static /**synchronized*/ SatietySingleton getInstance(){ if (instance == null){ instance = new SatietySingleton(); } return instance; } }
3.最优方案(线程安全,且效率最高)
public class BestSingleton {
//定义一个私有构造方法
private BestSingleton(){
}
//定义一个静态私有变量(不初始化,不使用final关键字,使用volatitle保证了多线程访问时instance变量的可见性,
//避免instance初始化时其他变量属性还没赋值完事,被另外的线程调用
private static volatile BestSingleton instance;
//定义一个共有的静态方法,返回该类型实例
public static BestSingleton getInstance(){
//对象实例化时与否判断(不实用同步代码块,instance不等于null时,直接返回对象,提高运行效率
if (instance == null){
//同步代码块(对象未初始化时,使用同步代码块,保证多线程访问时对象在第一次创建后,不再重复被创建
synchronized(BestSingleton.class){
//未初始化,则初始instance变量
if (instance == null){
instance = new BestSingleton();
}
}
}
return instance;
}
}
博客链接:https://qiuxx404.github.io/2018/06/13/原创/设计模式/设计模式-单例模式