单例( 注意: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如首页页面缓存)。 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。 1、要求生产唯一序列号。 2.1. 饿汉式 2.2. 懒汉式 2.3. 双重锁检查 2.4. 静态内部类 2.5. 枚举实现
二十三种设计模式分类
一、概述
Singleton
)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows
中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。优点
2、避免对资源的多重占用(比如写文件操作)。缺点
应用场景
2、WEB
中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O
与数据库的连接等。
二、实现
1. 单例模式结构图
PS
:UML
结构图可以参考,例子实现并不根据UML
图来完成,灵活实现即可;2. 单例模式实现
在JVM
加载类阶段就构建对象,适合绝大部分场景,JVM
只加载一次类,保证了线程安全;public class Singleton01 { private static Singleton01 instance = new Singleton01(); private Singleton01() { } public static Singleton01 getInstance() { return instance; } public static void main(String[] args) { Singleton01 singleton01 = Singleton01.getInstance(); Singleton01 singleton011 = Singleton01.getInstance(); System.out.println("Compare:" + (singleton01 == singleton011)); } }
线程不安全,在需要时再构建对象,多个线程同时构建对象时,会构建出多个对象;public class Singleton02 { private static Singleton02 instance; private Singleton02(){ } public static Singleton02 getInstance() { if (instance == null) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton02(); } return instance; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(Singleton02.getInstance().hashCode()); }).start(); } } }
使用synchronized
类锁限制每次只能有一个线程可以构建新对象,两次判断instance
对象是否为null
,第一次判断如果为null
,则构建新对象;第二次判断是否为null
,则是为了防止A线程已经构建完成了对象,避免B
线程获得锁后再次构建对象,确保该类只有一个实例;public class Singleton03 { ///volatile防止指令重排序 private volatile static Singleton03 instance; private Singleton03(){ } public static Singleton03 getInstance() { if (instance == null) { synchronized (Singleton03.class) { if (instance == null) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton03(); } } } return instance; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(Singleton03.getInstance().hashCode()); }).start(); } } }
静态内部类模式,JVM
加载静态内部类只会加载一次,加载过程中完成了新对象构建,保证了线程安全,不能解决反序列化问题;public class Singleton04 { private Singleton04(){ } //使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象 private static class SingletonHolder{ private static Singleton04 instance = new Singleton04(); } public static Singleton04 getInstance() { return SingletonHolder.instance; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(Singleton04.getInstance().hashCode()); }).start(); } } }
枚举没有构造函数,所以可解决反序列化的问题,并且保证线程安全;·public enum Singleton05 { /** * 单一实例 */ INSTANCE; public static Singleton05 getInstance() { return Singleton05.INSTANCE; } public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Singleton05 singleton1 = Singleton05.INSTANCE; Singleton05 singleton2 = Singleton05.INSTANCE; System.out.println("正常情况下,实例化两个实例是否相同:" + (singleton1 == singleton2)); Constructor<Singleton05> constructor = null; constructor = Singleton05.class.getDeclaredConstructor(); constructor.setAccessible(true); Singleton05 singleton3 = null; singleton3 = constructor.newInstance(); System.out.println(singleton1 + "n" + singleton2 + "n" + singleton3); System.out.println("通过反射攻击单例模式情况下,实例化两个实例是否相同:" + (singleton1 == singleton3)); } }··
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算