设计模式二 单例模式
设计模式二 单例模式
- 单例模式使用场景
- 1.饿汉式
- 2. 懒汉式
- 2.1 懒汉式实现一
- 2.2 懒汉式实现二
- 2.3 懒汉式实现三
- 3. 注册式
- 4. 枚举式
- 5. 序列化反序列化
单例模式使用场景
单例模式终极目的就是实现共享数据,保证程序运行过程中只会有一份数据。
它的常见应用场景:日历Calendar类,配置文件Config等等。
1.饿汉式
懒汉式单例的实现主要是以空间换时间策略,线程绝对安全。
/*** @author vigoss* @Description: 饿汉式单例* @date 2018/11/19 12:39*/
/*** 优点:* 1,对用户而言,饿汉式单例在设计时没有用到同步锁(synchronized)程序执行效率会比后续的懒汉式单例高* 2,线程绝对安全(这也是为什么不需要加synchronized的原因),单例对象在类加载的时候就创建了 ,线程只是负责去获取相应的实例* 缺点:* 1,类加载后就创建了实例,有点浪费内存资源,不管后续有没有使用*/
public class HungrySingleton {/***私有构造器 避免被程序在外部直接new创建出来*/private HungrySingleton() { }private static final HungrySingleton instance = new HungrySingleton();public static HungrySingleton getInstance(){return instance;}
}
/*** 饿汉式单例测试类*/
public class HungrySingletonTest {public static void main(String[] args) {HungrySingleton singleton =HungrySingleton.getInstance();System.out.println(singleton);}
}
- 优点:
1.对用户而言,饿汉式单例在设计时没有用到同步锁(synchronized)程序执行效率会比后续的懒汉式单例高。
2.线程绝对安全(这也是为什么不需要加synchronized的原因)单例对象在类加载的时候就创建了 ,线程只是 负责去获取相应的实例 - 缺点:
1.类加载后就创建了实例,有点浪费内存资源,不管后续有没有使用
2. 懒汉式
2.1 懒汉式实现一
/*** @author vigoss* @Description: 懒汉式单例模式一* @date 2018/11/19 13:00*/
/***优点:* 1,程序执行效率较高 没有加同步锁(synchronized)* 2,避免内存资源浪费 ,程序用到的时候才创建单例实例* 缺点:* 1,线程不安全*/
public class LazySingletonOne {/***私有构造器 避免被程序在外部直接new创建出来*/private LazySingletonOne() {}private static LazySingletonOne instance =null;public static LazySingletonOne getInstance() {if (instance == null) {instance = new LazySingletonOne();}return instance;}}
/*** @author vigoss* @date 2018/11/19 15:19*/
public class MockThreadOnSafe {public static void main(String[] args) {int count = 200;CountDownLatch latch = new CountDownLatch(count);for (int i = 0; i < count; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {//阻塞//等待发令枪 count=0 时一起唤醒所有线程latch.await();} catch (InterruptedException e) {e.printStackTrace();}//发令枪count=0后 可能会有多个线程同时去访问getInstance();LazySingletonOne singletonOne = LazySingletonOne.getInstance();System.out.println("当前获取的单例实例:"+singletonOne);}}).start();//count--latch.countDown();}}
}
结果
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7858e8ff
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@2dcc7385
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@58b48bb4
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@4b55e8db
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
当前获取的单例实例:com.wlj.learn.pattern.singleton.lazy.LazySingletonOne@7025de1
......
- 优点:
1.程序执行效率较高 没有加同步锁(synchronized)
2.避免内存资源浪费 ,程序用到的时候才创建单例实例 - 缺点:
1.线程不安全
2.2 懒汉式实现二
以时间换空间的实现方式
/*** @author vigoss* @date 2018/11/19 16:27*//*** 优点:* 1,线程安全* 2,内存使用更为合理,单例在需要的时候才被创建实例* 缺点:程序执行效率没有懒汉式高*/
public class LazySingletonTwo {/***私有构造器 避免被程序在外部直接new创建出来*/private LazySingletonTwo(){}private static LazySingletonTwo instance = null;public static synchronized LazySingletonTwo getInstance() {if (instance == null) {instance = new LazySingletonTwo();}return instance;}
}
- 优点:
1.线程安全
2.内存使用更为合理,单例在需要的时候才被创建实例, - 缺点:
1.程序执行效率没有懒汉式高
2.3 懒汉式实现三
兼顾时间和空间的实现方式 比较完美
*** @author vigoss* @date 2018/11/19 17:06*//*** 外部类加载时 静态内部类不会加载 当调用getInstance()方法时内部类才去加载,这个时候就会创建外部类单例实例,避免了内存浪费。* 没有使用同步锁 ,兼顾了饿汉式的程序执行效率以及懒汉式的合理利用内存资源 比较完美*缺点:无法动态传参*/
public class LazySingletonThree {/***私有构造器只能被自己或者内部类调用 避免被程序在外部直接new创建出来*/private LazySingletonThree(){}public static final LazySingletonThree getInstance() {return LazySingletonHolder.LAZY_SINGLETON_THREE;}/*** 静态内部类 在外部类调用getInstance时jvm才加载,同时初始化LAZY_SINGLETON_THREE字段并创建外部类的单例实例。* 这种方式不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。*/private static class LazySingletonHolder{private static final LazySingletonThree LAZY_SINGLETON_THREE = new LazySingletonThree();}}
使用静态内部类的优点:外部类在加载时不会去加载静态内部类,当外部类调用getInstance()方法时才去加载内部类LazySingletonHolder,同时初始化LAZY_SINGLETON_THREE字段并创建外部类的单例实例。所以比较节省内存空间。这种方式不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。
缺点:由于单例是被静态内部类初始化的,所以无法动态传入参数。
3. 注册式
spring中注册式单例
/*** @author vigoss* @date 2018/11/19 19:10*/
/*** spring 中的注册式单例*/
public class BeanFactory {private BeanFactory(){}/*** 线程安全*/private static Map<String, Object> ioc = new ConcurrentHashMap<>();public static Object getBean(String beanName){synchronized (BeanFactory.class){if (!ioc.containsKey(beanName)) {Object obj =null;try {Class<?> clazz = Class.forName(beanName);Constructor constructor = clazz.getDeclaredConstructor(null);obj = constructor.newInstance();ioc.put(beanName, obj);} catch (Exception e) {e.printStackTrace();}return obj;}else{return ioc.get(beanName);}}}
}
/*** @author vigoss* @date 2018/11/19 19:20*//*** BeanFactoryTest类 模拟线程不安全访问*/
public class BeanFactoryTest {public static void main(String[] args) {int count = 200;//发令枪CountDownLatch latch = new CountDownLatch(count);long start = System.currentTimeMillis();for (int i = 0; i < count;i ++) {new Thread(){@Overridepublic void run() {try{try {// 阻塞// count = 0 就会释放所有的共享锁// 万箭齐发latch.await();}catch(Exception e){e.printStackTrace();}//必然会调用,可能会有很多线程同时去访问getInstance()Object obj = BeanFactory.getBean("com.wlj.learn.pattern.singleton.test.TestPojo");System.out.println(System.currentTimeMillis() + ":" + obj);}catch (Exception e){e.printStackTrace();}}}.start(); //每循环一次,就启动一个线程,具有一定的随机性//每次启动一个线程,count --latch.countDown();}long end = System.currentTimeMillis();System.out.println("总耗时:" + (end - start));}
}
结果
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270182:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
1542627270184:com.wlj.learn.pattern.singleton.test.TestPojo@2cc4a136
...
4. 枚举式
/*** @author vigoss* @date 2018/11/20 13:10*//*** 枚举单例模式*/
public enum DataResource {INSTANCE;private DataResource(){//只会初始化一次 这就从根本上保证了Resource的单例instance = new Resource();}//数据源private Resource instance=null;public Resource getInstance() {return instance;}
}
class Resource{}
/*** @author vigoss* @date 2018/11/19 20:06*/
public class DataResourceTest {public static void main(String[] args) {int count = 200;CountDownLatch latch = new CountDownLatch(count);for (int i = 0; i < count; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {//阻塞//等待发令枪 count=0 时一起唤醒所有线程latch.await();} catch (InterruptedException e) {e.printStackTrace();}//发令枪count=0后 可能会有多个线程同时去访问getInstance();Object obj = DataResource.INSTANCE.getInstance();System.out.println("当前获取的单例实例:"+obj);}}).start();//count--latch.countDown();}}
}
结果
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
当前获取的单例实例:com.wlj.learn.pattern.singleton.enumor.Resource@7da3012d
.....
5. 序列化反序列化
/*** @author vigoss* @date 2018/11/19 20:23*//*** 解决反序列化时单例被破坏*/
public class SerialSingleton implements Serializable{private static SerialSingleton instance = null;private SerialSingleton(){if (instance!=null)throw new RuntimeException("单例已被初始化");}public static synchronized SerialSingleton getInstance() {if (instance == null) {instance = new SerialSingleton();}return instance;}private Object readResolve(){return instance;}
}
/*** @author vigoss* @date 2018/11/19 20:31*/
public class SerialSingletonTest {public static void main(String[] args) {SerialSingleton s1 = null;SerialSingleton s2 = SerialSingleton.getInstance();FileOutputStream fos = null;try {fos = new FileOutputStream("Seriable.obj");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(s2);oos.flush();oos.close();FileInputStream fis = new FileInputStream("Seriable.obj");ObjectInputStream ois = new ObjectInputStream(fis);s1 = (SerialSingleton)ois.readObject();ois.close();System.out.println(s1);System.out.println(s2);System.out.println(s1 == s2);} catch (Exception e) {e.printStackTrace();}}
}
结果
com.wlj.learn.pattern.singleton.searializable.SerialSingleton@372f7a8d
com.wlj.learn.pattern.singleton.searializable.SerialSingleton@372f7a8d
true
设计模式二 单例模式相关推荐
- Java设计模式(二) -- 单例模式
单例模式是Java中最广泛应用的设计模式之一,为创建对象提供了一种绝佳的方式.因此,在一些Java程序中, 一些管理器和控制器经常被设计为单例模式. 这种模式涉及到一个单一的类,该类负责创建自己的对象 ...
- php 单例模式 序列化,php设计模式(二)单例模式
应用场景: 数据库连接这种比较耗费资源的操作: 我们希望整个应用只实例化一个: 结构: 4私1公: 私有化构造方法: 防止使用 new 创建多个实例: 私有化克隆方法: 防止 clone 多个实例: ...
- 从王者荣耀看设计模式(二.单例模式)
从王者荣耀看设计模式(单例模式) 一:简介 多个英雄可同时攻击敌方水晶,当水晶血条小于0,游戏结束 二:单例模式 一个类有且仅有一个实例,并且自行实例化向整个系统提供(水晶). 这其中的设计原则有: ...
- 【白话设计模式二】外观模式(Facade)
为什么80%的码农都做不了架构师?>>> #0 系列目录# 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factory) [白话设计模式二] ...
- C#设计模式(1)——单例模式
原文地址:http://www.cnblogs.com/zhili/p/SingletonPatterm.html 一.引言 最近在设计模式的一些内容,主要的参考书籍是<Head First 设 ...
- 设计模式之单例模式——Singleton
设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...
- 【白话设计模式二十二】解释器模式(Interpreter)
为什么80%的码农都做不了架构师?>>> #0 系列目录# 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factory) [白话设计模式二] ...
- java 23种设计模式 04 单例模式
java 23种设计模式 04 单例模式 一.什么是单例模式 单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象.也就是说,在整个程序空间中,该类只存在一个实例对象. ...
- 23种设计模式之单例模式、工厂模式、原型模式、建造者模式
系列文章目录 第一章:程序设计原则-单一职责.接口隔离.依赖倒置.里式替换 第二章:程序设计原则-开闭原则.迪米特法则.合成复用原则 文章目录 系列文章目录 一.设计模式简单介绍 1.1.什么是设计模 ...
- java_设计模式_单例模式_
目录 引言 一.概述 1.概念: 2.单例模式有 3 个特点: 3.单例模式的优点和缺点: 单例模式的优点: 单例模式的缺点: 单例模式的应用场景: 单例模式的结构: 二.单例模式的实现 1.饿汉式单 ...
最新文章
- SystemCenter2012SP1实践(5)SCVMM管理HyperV
- 数据结构基础(4) --快速排序
- linux里面vim自动显示行号,linux中vim永久显示行号、开启语法高亮
- docker-安装、使用centos7镜像
- Web服务器性能/压力测试工具http_load、webbench、ab、Siege
- 批量图片验证模型错误: OP_REQUIRES failed at save_restore_v2_ops.cc:184 : Not found: Key conv1_1/bias not found
- python socketserver实现tcp post,get请求
- 复旦赵卫东:大数据的系统观
- 【微软算法面试高频题】可怜的小猪
- Spring学习手记(二)——控制台调度任务
- Android 人脸识别签到(二)
- 目标检测模型从训练到部署,其实如此简单
- 小刚明白锻炼的重要性,每天坚持走10000步。这一天,他已经走了一些步,想知道还要走多少步才能完成这一天的锻炼任务。请你帮帮他。
- 第10章两个独立样本的t检验
- yapi接口导出为word_还在手工写接口测试文档,已经out了
- Bootstarp未读消息铃铛
- Go语言学习二 语言结构 基础语法 数据类型
- 构建module遇到pom报错Parent 'Unkown:Unkown:Unkown' has problems
- 新科技革命的主要特点
- 2012年度最佳Web前端开发工具和框架总结