前言:单例模式大家应该很熟悉了,我在这里就自己总结一下自己这段时间学到的单例相关的知识。
单例模式的目的:保证一个类只有单一的实例,也就是说你无法通过new来创建这个类的一个新实例。
单例模式的意义:保证一个类只有单一的实例,也就是说你无法通过new来创建这个类的一个新实例。我们可以控制类对象的产生的数目。
单例模式使用场合:
使用单例的情况有3种:
1、类a从类b继承,这时a需使用单例才能直接访问b中声明的变量和方法
2、类a将被类b继承,这时a也需要使用单例,否则b将无法直接使用a的方法
3、单例可以提供一个构造函数,确保使用该单例时能够初始化一些环境,比如从外部读入配置文件,或者和外部建立基本通信等
几种实现方式(均为线程安全的实现方式):
1. 饿汉式:
public class Singleton { private Singleton(){ System.out.println("Singleton is create"); } private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } }
这种实现方式也被我们称为饿汉式单例模式,宗旨就是不管你要不要,我先提前new出来,这肯定是线程安全的,因为new的动作发生在第一次访问类的时候。
缺点:可能会出现不必要的实例化。也就是我不想获取实例,它却自己做了,这样会降低效率。
例子:
public class Singleton { public static int STATUS=1; private Singleton(){ System.out.println("Singleton is create"); } private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } }
我仅仅想访问Singleton里面的一个静态字段,结果他还执行了一次new对象的操作。
2.同步方法:
public class LazySingleton { private LazySingleton() { System.out.println("LazySingleton is create"); } private static LazySingleton instance = null; public static synchronized LazySingleton getInstance() { if (instance == null) instance = new LazySingleton(); return instance; } }
这种方式虽然解决了线程安全和没做多余的动作的要求,但是由于是在整个getInstance方法加了synchronized,导致一次只能一个线程调用getInstance方法,会影响程序运行效率。
3.同步代码块(Double Check)
public Resource getResource() { if (resource == null) { synchronized(this){ if (resource==null) { resource = new Resource(); } } } return resource; }
很不错的解决方案,但是首先需要将单例声明为volatile类型以保证线程安全,其次,用了同步代码块,所以也是会影响效率,不过比
之前几个好很多。
4.内部静态类:
public class StaticSingleton { private StaticSingleton(){ System.out.println("StaticSingleton is create"); } private static class SingletonHolder { private static StaticSingleton instance = new StaticSingleton(); } public static StaticSingleton getInstance() { return SingletonHolder.instance; } }
这种方式没用到同步,但是很好的解决了之前几种情况的缺点。
时间: 2024-09-29 08:41:24