IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 单例模式(对象私有化) -> 正文阅读

[Java知识库]单例模式(对象私有化)

单例模式(对象私有化)

目录

单例模式(对象私有化)

1.介绍

应?实例:

优点:

缺点:

使?场景:

2.实现

3 单例模式实现?式

3.1 饿汉式

3.2 懒汉式

3.3 双检锁/双重校验锁

3.4 登记式/静态内部类

3.5 枚举式


单例模式(Singleton Pattern)是Java中最简单的设计模式之?。这种类型的设计模式属于创建型模式,它提供了 ?种创建对象的最佳?式。这种模式涉及到?个单?的类,该类负责创建??的对象,同时确保只有单个对象被创建。这个类提供了?种访问其唯?的对象的?式,可以直接访问,不需要实例化该类的对象

注意:

1.单例类只能有?个实例。

2.单例类必须??创建??的唯?实例。

3.单例类必须给所有其他对象提供这?实例。

1.介绍

意图:保证?个类仅有?个实例,并提供?个访问它的全局访问点。

主要解决:?个全局使?的类频繁地创建与销毁。

何时使?:当你想控制实例数?,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

应?实例:

1.多个进程或线程同时操作?个?件,所以所有?件的处理必须通过唯?的实例进?。

2.?些设备管理器常常设计为单例模式,?如?个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同?个?件。

优点:

1.在内存?只有?个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

2.避免对资源的多重占?(?如写?件操作)。

缺点:

没有接?,不能继承,与单?职责原则冲突,?个类应该只关?内部逻辑,?不关?外?怎么样来实例化。

使?场景:

1.要求?产唯?序列号。

2.WEB中的计数器,不?每次刷新都在数据库?加?次,?单例先缓存起来。

3.创建的?个对象需要消耗的资源过多,?如I/O与数据库的连接等。

2.实现

我们将创建?个SingleObject类。SingleObject类有它的私有构造?法和本身的?个静态实例。 SingleObject类提供了?个静态?法,供外界获取它的静态实例。

3 单例模式实现?式

3.1 饿汉式

提前将对象准备好,加载到内存中

3.1.1 饿汉式介绍

是否Lazy初始化:否 (提前准备好对象)

是否多线程安全:是 (饿汉式只有一个实例,没有多线程)

描述:这种?式?较常?,但容易产?垃圾对象。 (可能创建出来的对象一直没有用)

优点:没有加锁,执?效率会提?。

缺点:类加载时就初始化,浪费内存。

它基于classloader机制避免了多线程的同步问题,不过instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中?多数都是调?getInstance()?法, 但是也不能确定有其他的?式(或者其他的静态?法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

3.1.2 饿汉式案例

1.创建?个Java项?。

2.创建?个HungrySingleton类。

package com.设计模式.饿汉式;
public class HungrySingleton {
 ? ?//设置为静态,实现全局访问              //提前将对象准备好,加载到内存中
 ? ?private static HungrySingleton instance = new HungrySingleton();
 ? ?//构造方法私有化目的是为了在其他类里不能创建该对象
 ? ?private HungrySingleton(){}
 ? ?//提供静态方法来访问类中的私有成员
 ? ?public static HungrySingleton getInstance(){
 ? ? ? ?return instance;
 ?  }
 ? ?public void showMessage(){
 ? ? ? ?System.out.println("创建instence成功,showMessage执行了");
 ?  }
}

3.从HungrySingleton类获取唯?的对象。

package com.设计模式.饿汉式;
public class Test_HungrySingleton {
 ? ?public static void main(String[] args) {
 ? ? ? ?HungrySingleton hungrySingleton = HungrySingleton.getInstance();
 ? ? ? ?hungrySingleton.showMessage();
 ?  }
}

4.执?程序,输出结果。

3.2 懒汉式

什么时候使用对象,什么时候创建对象

3.2.1 懒汉式线程不安全

3.2.1.1 懒汉式线程不安全介绍

是否Lazy初始化:是 (懒汉式是在对象真正需要被实例化的时候,才去创建对象)

是否多线程安全:否 (多线程同时进行到if时,可能创建多个instance)

描述:这种?式是最基本的实现?式,这种实现最?的问题就是不?持多线程。因为没有加锁synchronized,所以严格意义上它并不算单例模式。

这种?式lazy loading很明显,不要求线程安全,在多线程不能正常?作。

3.2.1.2 懒汉式线程不安全案例

1.创建?个LazySingleton类。

package com.设计模式.懒汉式.线程不安全;
 ? ?/*
 ? ? ? ?什么时候使用对象,什么时候创建对象  (懒加载)
 ? ? */
public class LazySingleton {
 ? ?private static LazySingleton instance;
 ? ?private LazySingleton (){}
 ? ? public static LazySingleton getInstance(){
 ? ? ? ?if (instance == null){
 ? ? ? ? ? ?instance = new LazySingleton();
 ? ? ?  }
 ? ? ? ?return instance;
 ? ? }
 ? ? public void showMessage(){
 ? ? ? ? System.out.println("创建instance成功,showMessage执行了");
 ? ? }
}

2.从LazySingleton类获取唯?的对象。

package com.设计模式.懒汉式.线程不安全;
import com.设计模式.懒汉式.线程不安全.LazySingleton;
public class Test_LazySingleton {
 ? ?public static void main(String[] args) {
 ? ? ? ?LazySingleton lazySingleton = LazySingleton.getInstance();
 ? ? ? ?lazySingleton.showMessage();
 ?  }
}

3.执?程序,输出结果。

3.2.2 懒汉式线程安全

3.2.2.1 懒汉式线程安全介绍

是否Lazy初始化:是

是否多线程安全:是 (加了锁)

描述:这种?式具备很好的lazy loading,能够在多线程中很好的?作,但是效率很低,99%情况下不需要同步。

优点:第?次调?才初始化,避免内存浪费

缺点:必须加锁synchronized才能保证单例,但加锁会影响效率

getInstance()的性能对应?程序不是很关键(该?法使?不太频繁)。

3.2.2.2 懒汉式线程安全案例

对原来类中的getInstance()方法?synchronized修饰。

package com.设计模式.懒汉式.线程安全;
/*
 ? ?什么时候使用对象,什么时候创建对象
 */
public class LazySingleton {
 ? ? ? ?private static LazySingleton instance;
 ? ? ? ?private LazySingleton (){}
 ? ?//加锁变成多线程安全
 ? ? ? ?public static synchronized LazySingleton getInstance(){
 ? ? ? ? ? ? ? ?if (instance == null){
 ? ? ? ? ? ? ? ? ? ? ? ?instance = new LazySingleton();
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ?return instance;
 ? ? ?  }
 ? ? ? ?public void showMessage(){
 ? ? ? ? ? ? ? ?System.out.println("创建instance成功,showMessage执行了");
 ? ? ?  }
}

3.3 双检锁/双重校验锁

处在懒汉式的基础上,比懒汉式更高效

3.3.1 双检锁/双重校验锁介绍

是否Lazy初始化:是

是否多线程安全:是

描述:双检锁/双重校验锁(DCL,即double-checked locking),这种?式采?双锁机制,安全且在多线程情况下能保持?性能。

getInstance()的性能对应?程序很关键。

3.3.2 双检锁/双重校验锁案例

volatile是?个特征修饰符(type specifier)。volatile的作?是作为指令关键字,在指令层面保证当前对象的值不会被误读或恶意修改,确保本条指令不会因编译器的优化?省略,且要求每次直接读值。简单地说就是防?编译器对代码进?优化。

1.创建?个DCLSingleton类。

package com.设计模式.双检锁;
public class DCLSingleton {
 ? ?/*
 ? ?volatile:
 ? ? ? ?修饰类的属性的
 ? ? ? ?在指令层面保证当前对象的值不会被误读或恶意修改
 ? ? ? ?作用:确保本条指令所修饰的成员不会在编译的时候被省略,且每次都会直接读取它的值
 ? ? ? ?防止编译器优化此代码的风险
 ? ? */
 ? ?private volatile static DCLSingleton instance;
 ? ?private DCLSingleton (){}
 ? ?public static synchronized DCLSingleton getInstance(){
 ? ? ? ?if (instance == null){
 ? ? ? ? ? ?synchronized (DCLSingleton.class){
 ? ? ? ? ? ? ? ?if (instance == null){
 ? ? ? ? ? ? ? ? ? ?instance = new DCLSingleton();
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?return instance;
 ?  }
 ? ?public void showMessage(){
 ? ? ? ?System.out.println("创建instance成功,showMessage执行了");
 ?  }
}
?

2.从DCLSingleton类获取唯?的对象。

package com.设计模式.双检锁;
public class Test_DCLSingleton {
 ? ?public static void main(String[] args) {
 ? ? ? ?DCLSingleton dclSingleton = DCLSingleton.getInstance();
 ? ? ? ?dclSingleton.showMessage();
 ?  }
}

3.执?程序,输出结果。

3.4 登记式/静态内部类

内部类只有在外部类被调用才加载,产生INSTANCE实例,又不用加锁,此模式有懒汉式 和饿汉式的优点,屏蔽了他们的缺点,是最好的单例模式

3.4.1 登记式/静态内部类介绍

是否Lazy初始化:是 (在一开始的时候内部类不会被加载,内部类只有被调用的时候才会被加载)

是否多线程安全:是 (classloader机制为其自动加了锁)

描述:这种?式能达到双检锁?式?样的功效,但实现更简单。对静态域使?延迟初始化,应使?这种?式?不是双检锁?式。这种?式只适?于静态域的情况,双检锁?式可在实例域需要延迟初始化时使?。 这种?式同样利?了classloader机制来保证初始化instance时只有?个线程,它跟饿汉式不同的是:饿汉式只要HungrySingleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),?这种?式是RegisterSingleton类被装载了,instance不?定被初始化。因为Test_RegisterSingleton类没有被主动使?,只有通过显式调?getInstance?法时,才会显式装载SingletonHolder类,从?实例化instance。想象?下,如果实例化instance很消耗资源,所以想让它延迟加载,另外???,还要保证多线程安全,因为不能确保Singleton类还可能在其他的地?被主动使?从?被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种?式相?饿汉式?式就显得很合理。

3.4.2 登记式/静态内部类案例

1.创建?个RegisterSingleton类。

package com.设计模式.登记式;
 ? ?/*
 ? ?* 登记式/静态内部类:
 ? ?* 1.在单例类中声明一个静态内部类
 ? ?* 2.在这个静态内部类中声明单例对象,并且初始化这个对象
 ? ?* */
public class RegisterSingleton {
 ? ?private static class SingletonHolder {
 ? ? ? ?//创建私有化的静态常量
 ? ? ? ?private static final RegisterSingleton INSTANCE = new RegisterSingleton();
 ?  }
 ? ? ? ?private RegisterSingleton (){}
 ? ? ? ?//final修饰的方法不能被重写
 ? ? ? ?public static final RegisterSingleton getInstance(){
 ? ? ? ?return SingletonHolder.INSTANCE;
 ? ? ?  }
 ? ? ? ?public void showMessage(){
 ? ? ? ? ? ?System.out.println("INSTANCE创建成功,showMessage执行了");
 ? ? ?  }
}

2.从RegisterSingleton类获取唯?的对象。

package com.设计模式.登记式;
?
public class Test_RegisterSingleton {
 ? ?public static void main(String[] args) {
 ? ? ? ?RegisterSingleton registerSingleton = RegisterSingleton.getInstance();
 ? ? ? ?registerSingleton.showMessage();
 ?  }
}

3.执?程序,输出结果。

3.5 枚举式

3.5.1 枚举式介绍

是否Lazy初始化:否

是否多线程安全:是

描述:这种实现?式还没有被?泛采?,但这是实现单例模式的最佳?法。它更简洁,?动?持序列化机制,绝对防?多次实例化。 这种?式是Effective Java作者Josh Bloch提倡的?式,它不仅能避免多线程同步问题,?且还?动?持序列化机 制,防?反序列化重新创建新的对象,绝对防?多次实例化。不过由于JDK1.5后才加?enum特性,?这种?式写 不免让?感觉?疏,在实际?作中,也很少?。 不能通过reflection attack来调?私有构造?法。

3.5.2 枚举式案例

1.创建?个EnumSingleton枚举类。

package com.设计模式.枚举式;
?
public enum EnumSingleton {
 ? ?//枚举常量可以作为枚举内部定义方法的访问
 ? ?INSTANCE;
 ? ?/*
 ? ?* 1.枚举类型中定义的变量只能是常量
 ? ?* 2.枚举类型中定义方法(和class类结构中定义的方法完全一样)
 ? ?* */
 ? ?public void showMessage(){
 ? ? ? ?System.out.println("EnumSingleton类中的showMessage");
 ?  }
}
?

2.从EnumSingleton枚举类获取唯?的枚举类型数据。

package com.设计模式.枚举式;
?
public class Test_EnumSingleton {
 ? ?public static void main(String[] args) {
 ? ? ? ?EnumSingleton.INSTANCE.showMessage();
 ?  }
}
?

3.执?程序,输出结果。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:49:43  更:2022-03-31 23:52:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:52:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码