单例模式也叫做单肩模式,也是一种创建型模式,是我们日常开发中最常使用的一种设计模式,经常被用来封装一些工具类,例如数据库连接等。
<强>单例模式的定义:
强>
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例
单例模式分为以下几种:
①饿汉单例模式
②懒汉单例模式
③IoDH单例模式
④枚举单例模式
下面我们一一的进行介绍:
1。首先是饿汉单例模式,顾名思义“饿汉”,代表急着吃“饭”(这里的饭应该是指的实例对象),所以很早就创建出不来。多说,上代码:
包单; 公开课HungrySingletonP { 私有静态HungrySingletonP实例=new HungrySingletonP (); 公共HungrySingletonP () {} 公共静态HungrySingletonP getInstance () { 返回实例; } } >之前这段代码很形象的体现了饿汉模式。
这种方法在类加载的时候就已经实例化了(只创建唯一的实例),所以不存在线程上的一些问题。但是,也因为如此如果有太多的单例,且这些实例不经常使用那么久会造成对内存的浪费。
2。懒汉模式,同样什么叫做懒汉模式?一个懒惰的人,只有去吃饭的时候才会去刷碗(昨天用过的脏碗),即:只有当用到对象的时候才去创建对象,来上代码:
包单; 公开课LasySingletonV1 { 私有静态LasySingletonV1实例; 公共LasySingletonV1 () {} 公共静态LasySingletonV1 getInstance () { 如果(实例==null) { 返回新LasySingletonV1 (); 其他} 返回实例; } } >之前上面的这段代码是懒汉模式,当我们不需要实例的时候,它不会创建实例,只有需要实例的时候,才会创建,节省空间。
但是,我们不推荐使用,因为我们原来的设计理念是:当需要的时候(并且实例为空)创建实例,当已经创建过后,如果还需要实例,则判断实例是否为空,因为前边已经创建过了,不为空,所以直接返回之前已经创建的实例。
以上的想法是很好的,但是它是线程不安全的。因为:当有多个线程同时调用这个方法时,因为同时判断实例为空,所以会创建很多个实例,这不符合单例模式的设计理念(一个类只有一个实例对象)。所以我们需要对它进行改进,因为它会异步创建多个实例,多以我们很容易就能想的到,在getInstance方法之前加上同步进行同步:
包单; 公开课LasySingletonV2 { 私有静态LasySingletonV2实例; 公共LasySingletonV2 () {} 公共同步LasySingletonV2 getInstance () { 如果(实例==null) { 返回新LasySingletonV2 (); 其他} 返回实例; } } >之前上面这样,就不会创建多个实例对象符合单例模式的概念。
但是上面这样的设计使得我们每次需要目标实例的时候都要排队等待,假设有很多线程都在调用这个getInstance方法,那么就会陷入很长时间的等待,大大降低的程序的效率。
所以我们还要对程序进行一定的修改,如果我们创建一个
包单; 公开课LasySingletonV3 { 私有静态LasySingletonV1实例; 公共LasySingletonV3 () {} 公共LasySingletonV3 getInstance () { 如果(实例==null) { 同步(LasySingletonV3.class) { 如果(实例==null) { 返回新LasySingletonV3 (); } } } 返回实例; } } >之前以上的方法是懒汉模式的完整版本,我们来仔细分析一下:
当有多个线程第一次调用这个方法的时候,都满足实例为空,来到下一步,先获得锁的线程进入下一步继续判断是否为空,为空,然后创建实例返回实例。
没有获得锁的线程一直等待到获得锁的线程释放锁,当在等待的线程获得锁的时候进入下一步,还要进行判断实例是否为空,但是这个时候实例已经不为空了,因为前面的线程已经创建了实例,所以返回已经创建好的实例。
java设计模式之单例模式