确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例
1. 内存中只有一个实例,减小内存开支 2. 减小对象频繁的建立、销毁 3. 建立资源时须要比较多的资源时减小,减小性能开销 4. 避免对资源的多重占用 5. 在系统设置全局访问点,优化和共享资源访问
1. 没有接口,扩展困难 2. 与单一原则职责有冲突,一个类应该只实现本身的逻辑,并不须要关心它是否单例的, 是否是单例取决与环境,单例模式把 “要单例”和业务逻辑融合了(能够用内部类持有单例的方式解决此问题)
系统要求某个类有且只有一个实例,不然就会出现“不良反应”
具体场景举例java
生成惟一的序列号 项目中须要一个共享访问点或共享数据
须要产生多个固定数量或有上限数量对象的模式就叫多例模式。能够在设计系统的时候决定系统产生多少个 实例,方便进行扩展,修正单例存在的性能问题,提供响应速度
· 简单类的单例安全
类被加载时就会被实例化一个对象
· 优势ide
线程安全
· 缺点性能
不能被延迟加载 没有被调用状况,浪费系统资源
· 实现方式测试
public class SimpleHungrySingleInstance { private static final SimpleHungrySingleInstance instance = new SimpleHungrySingleInstance(); private SimpleHungrySingleInstance(){ } public static SimpleHungrySingleInstance getSingleInstance(){ return instance; } }
枚举只能拥有私有的构造器优化
枚举类其实是一个继承 Enum 的一个 final 类线程
枚举类不容许被反序列化,Enum 重写了方法设计
静态代码块中对 final 变量的值进行初始化指针
enum 类最终是一个 final classcode
/** * 利用枚举实现单例 * */ public class ThreadSafeSingleInstanceFactoryFive { private ThreadSafeSingleInstanceFactoryFive(){ } private enum SingleFactoryEnum{ SINGLE_FACTORY_ENUM { @Override public void doSomeThing() { } }; private Cat cat = null; public void doSomeThing(){ System.out.println("cat.hashCode=" + cat.hashCode()); } SingleFactoryEnum(){ cat = new Cat(); } } public static Cat getCat(){ return SingleFactoryEnum.SINGLE_FACTORY_ENUM.cat; } public static void doSomeThing(){ SingleFactoryEnum.SINGLE_FACTORY_ENUM.doSomeThing(); }
只在须要对象时才会生成单例对象
· 优势
能延迟加载
· 缺点
须要本身保证线程安全
· 实现方式
synchronized 方法获取
线程安全,锁粒度为Class,粒度较大,性能受影响
public class ThreadSafeSingleInstanceModelOne { private static ThreadSafeSingleInstanceModelOne threadSafeSingleInstanceModelOne = null; private ThreadSafeSingleInstanceModelOne(){ } /** * * @return */ public synchronized static ThreadSafeSingleInstanceModelOne getInstance(){ if(threadSafeSingleInstanceModelOne == null){ try { Thread.sleep(300); //模拟实例化须要的时间 } catch (InterruptedException e) { e.printStackTrace(); } threadSafeSingleInstanceModelOne = new ThreadSafeSingleInstanceModelOne(); } return threadSafeSingleInstanceModelOne; } }
synchronized 同步块
非线程安全
public class ThreadSafeSingleInstanceModelTwo { private static ThreadSafeSingleInstanceModelTwo instance = null; public static ThreadSafeSingleInstanceModelTwo getInstance(){ if(instance == null){ // 多个线程可能会同时在这里判true,所以屡次进入同步块 synchronized (ThreadSafeSingleInstanceModelTwo.class){ try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } instance = new ThreadSafeSingleInstanceModelTwo(); } } return instance; } }
public class ThreadSafeSingleInstanceModelThree { /** * 采用Volatile 和 DCL机制 * * volatile 关键字做用 只能保证可见性 * 1,多个线程可见 * 2,禁止指令重排 * * 通常对象的建立步骤 分配地址 -> 初始化属性 -> 指针指向分配地址 * * 编译器优化致使指令重排 可能出现 * 分配地址 * -> 指针指向分配地址(没有初始化 返回是个null对象 原始类型范围内的值(例如int 的范围为-128 ~ 127 ,超事后自动转化为对象建立)) * -> 初始化属性 * * * * Double Check Locking 双检查锁机制(推荐) * 同步块中不检查的状况可能还会屡次建立对象 * */ private volatile static ThreadSafeSingleInstanceModelThree instance = null; public static ThreadSafeSingleInstanceModelThree getInstance() { if (instance == null) { synchronized (ThreadSafeSingleInstanceModelThree.class) { try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } if (instance == null) { //此处可能对象已经分配指针但没有初始化 采用 Double Check Locking 双检查锁机制 instance = new ThreadSafeSingleInstanceModelThree(); } } } return instance; } }
4.静态内部类的实现
/** * 静态内部类的单例 * 没有获取实例的时候内部类不会被初始化 */ public class ThreadSafeSingleInstanceModelFour { private static class ThreadSafeSingleInstanceModelFourInnerClass{ public static final ThreadSafeSingleInstanceModelFour instance = new ThreadSafeSingleInstanceModelFour(); } public static final ThreadSafeSingleInstanceModelFour getInstance(){ try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } return ThreadSafeSingleInstanceModelFourInnerClass.instance; } }
5.序列化
public class ThreadSafeSingleInstanceModelSix implements Serializable { /** * 序列化能够保证单例的安全 * 但反序列化的过程是readObject() 会建立一个新的对象,readResolve 特性容许你用 建立的实例代替另一个实例, * 该方法忽略了被反序列化的对象,所以返回类初始化建立的那个特殊的实例 * 所以 实例的序列 化形式不该该包含任何实际的数据;全部的实例字段都应该被声明为 。 * 事实上, 若是依赖readResolve 进行实例控制,带有对象引用类型的全部实例字段都必须声明为 transient 。 * */ private volatile static ThreadSafeSingleInstanceModelSix instance = null; //标记为transient private transient String testName = ""; public static ThreadSafeSingleInstanceModelSix getInstance() { if (instance == null) { synchronized (ThreadSafeSingleInstanceModelSix.class) { try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } if (instance == null) { //此处可能对象已经分配指针但没有初始化 采用 Double Check Locking 双检查锁机制 instance = new ThreadSafeSingleInstanceModelSix(); } } } return instance; } private Object readResolve() { // Return the one true Elvis and let the garbage collector // take care of the Elvis impersonator. return instance; } }
占用资源少,不须要延时加载 饿汉式 > 懒汉式
占用资源大,须要延时加载 懒汉式 > 饿汉式
public class SimpleSluggardSingleInstanceThread extends Thread{ @Override public void run() { log.info("Thread getInstance hashCode = {}", SimpleSluggardSingleInstance.getInstance().hashCode()); } } public SimpleSluggardSingleInstanceThread newSimpleSluggardSingleInstanceThread(){ return new SimpleSluggardSingleInstanceThread(); }
TestThreads.SimpleSluggardSingleInstanceThread[] threads = new TestThreads.SimpleSluggardSingleInstanceThread[len]; for (int i = 0; i < threads.length; i++) { threads[i] = TestThreads.getThreadHandler().newSimpleSluggardSingleInstanceThread(); } for (int i = 0; i < threads.length; i++) { threads[i].start(); }