一个类中只有一个实例, 且能够自行实例化提供这个实例, 同时提供全局访问的方法.
结构
1.构造私有化: 确保外部不能使用new直接创建对象
2.内部静态属性创建实例
3.对外公共静态获取对象方法
demo
/*** 单例模式* 1. 构造私有化: 确保外部不能使用new直接创建对象* 2. 内部静态属性创建实例* 3. 对外公共静态获取对象方法** @author liuzhihang* @date 2018/3/27 17:45*/public class SingletonPattern {private SingletonPattern() {}private static SingletonPattern singletonPattern = null;public static SingletonPattern getSingletonPattern() {if (singletonPattern == null) {singletonPattern = new SingletonPattern();}return singletonPattern;}}
分类
1.懒汉式: 懒汉模式, 项目启动时不生成对象, 而是在首次创建该对象的时候生成唯一实例
/*** 懒汉模式, 项目启动时不生成对象, 而是在首次创建该对象的时候生成唯一实例** @author liuzhihang* @date 2018/4/2 16:24*/public class LazyPattern {private LazyPattern() {}private static LazyPattern lazyPattern = null;public static LazyPattern getLazyPattern() {try {if (lazyPattern == null) {// 模拟一系列耗时操作Thread.sleep(50);lazyPattern = new LazyPattern();}} catch (InterruptedException e) {e.printStackTrace();}return lazyPattern;}}
2.饿汉式: 项目启动时, 进行加载, 会导致项目启动较慢, 并且无论后面是否用到都会进行加载
/**** 饿汉式单例模式* 项目启动时, 进行加载, 会导致项目启动较慢, 并且无论后面是否用到都会进行加载** @author liuzhihang* @date 2018/4/2 18:44*/public class HungerPattern {private HungerPattern() {}private static HungerPattern hungerPattern = new HungerPattern();public static HungerPattern getHungerPattern() {return hungerPattern;}}
测试用例
在多线程情况下对单例模式进行测试:
/*** @author liuzhihang* @date 2018/3/27 19:02*/public class SingletonTest {public static void main(String[] args) {ThreadTest[] threadTests = new ThreadTest[10];for (int i = 0; i < threadTests.length; i++) {threadTests[i] = new ThreadTest();}for (int i = 0; i < threadTests.length; i++) {threadTests[i].start();}}}class ThreadTest extends Thread {@Overridepublic void run() {// 懒汉模式System.out.println(LazyPattern.getLazyPattern().hashCode());// 饿汉模式// System.out.println(HungerPattern.getHungerPattern().hashCode());}}
结果:
1.饿汉模式
D:\jdk1.8\bin\java.exe . . .1294123621129412362112941236211294123621129412362112941236211294123621129412362112941236211294123621Process finished with exit code 0
2.懒汉模式
D:\jdk1.8\bin\java.exe . . .14091981613591281341385166630924507082676413855088322625749263951409198161442414714896298396Process finished with exit code 0
懒汉模式的线程安全优化
饿汉模式会造成资源浪费, 启动慢等结果, 下面对懒汉模式进行线程安全优化.
synchronized 锁住静态方法
锁住静态方法 类级锁 影响范围较大, 导致效率相对较低
/*** 懒汉式* 在方法上添加 synchronized 关键字 锁类* 同步方法的方式, 导致效率相对较低** @author liuzhihang* @date 2018/4/3 14:27*/public class SyncLazyPattern {private SyncLazyPattern() {}private static SyncLazyPattern syncLazyPattern = null;public static synchronized SyncLazyPattern getSyncLazyPattern() {try {if (syncLazyPattern == null) {Thread.sleep(100);syncLazyPattern = new SyncLazyPattern();}} catch (InterruptedException e) {e.printStackTrace();}return syncLazyPattern;}}
synchronized 锁住代码块
package com.liuzhihang.demo.singleton;/*** 锁代码块的方式虽然可以保证结果一致性* 但锁住很多操作, 同样会导致效率低下** @author liuzhihang* @date 2018/4/3 15:22*/public class SyncCodeBlockLazyPattern {private SyncCodeBlockLazyPattern() {}private static SyncCodeBlockLazyPattern syncCodeBlockLazyPattern = null;public static SyncCodeBlockLazyPattern getSyncCodeBlockLazyPattern() {try {// 锁住具体执行业务逻辑的代码synchronized (SyncCodeBlockLazyPattern.class) {if (syncCodeBlockLazyPattern == null) {Thread.sleep(100);syncCodeBlockLazyPattern = new SyncCodeBlockLazyPattern();}}} catch (InterruptedException e) {e.printStackTrace();}return syncCodeBlockLazyPattern;}}
双重检查锁机制(推荐)
package com.liuzhihang.demo.singleton;/*** 双重锁检查机制, 仅锁住创建对象的部分代码* 注意: 在对象前 添加 volatile 关键字 确保可见性, 即 每次获取值从主内存中获取, 同时防止指令重排序** @author liuzhihang* @date 2018/4/3 15:29*/public class DubboCheckLockLazyPattern {private DubboCheckLockLazyPattern() {}private static volatile DubboCheckLockLazyPattern dubboCheckLockLazyPattern = null;public static DubboCheckLockLazyPattern getDubboCheckLockLazyPattern() {try {if (dubboCheckLockLazyPattern == null) {// 一系列操作Thread.sleep(100);synchronized (DubboCheckLockLazyPattern.class) {// 二次检查if (dubboCheckLockLazyPattern == null) {dubboCheckLockLazyPattern = new DubboCheckLockLazyPattern();}}}} catch (InterruptedException e) {e.printStackTrace();}return dubboCheckLockLazyPattern;}}
