一个类中只有一个实例, 且能够自行实例化提供这个实例, 同时提供全局访问的方法.
结构
1.构造私有化: 确保外部不能使用new直接创建对象
2.内部静态属性创建实例
3.对外公共静态获取对象方法
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public class SingletonPattern {
private SingletonPattern() { }
private static SingletonPattern singletonPattern = null;
public static SingletonPattern getSingletonPattern() {
if (singletonPattern == null) { singletonPattern = new SingletonPattern(); }
return singletonPattern; }
}
|
分类
1.懒汉式: 懒汉模式, 项目启动时不生成对象, 而是在首次创建该对象的时候生成唯一实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
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.饿汉式: 项目启动时, 进行加载, 会导致项目启动较慢, 并且无论后面是否用到都会进行加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public class HungerPattern {
private HungerPattern() { }
private static HungerPattern hungerPattern = new HungerPattern();
public static HungerPattern getHungerPattern() { return hungerPattern; } }
|
测试用例
在多线程情况下对单例模式进行测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
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 {
@Override public void run() { System.out.println(LazyPattern.getLazyPattern().hashCode()); } }
|
结果:
1.饿汉模式
1 2 3 4 5 6 7 8 9 10 11 12 13
| D:\jdk1.8\bin\java.exe . . . 1294123621 1294123621 1294123621 1294123621 1294123621 1294123621 1294123621 1294123621 1294123621 1294123621
Process finished with exit code 0
|
2.懒汉模式
1 2 3 4 5 6 7 8 9 10 11 12 13
| D:\jdk1.8\bin\java.exe . . . 140919816 1359128134 1385166630 924507082 67641385 508832262 574926395 140919816 1442414714 896298396
Process finished with exit code 0
|
结论: 在懒汉单例模式下不能保证线程的安全性
懒汉模式的线程安全优化
饿汉模式会造成资源浪费, 启动慢等结果, 下面对懒汉模式进行线程安全优化.
synchronized 锁住静态方法
锁住静态方法 类级锁 影响范围较大, 导致效率相对较低
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
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 锁住代码块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.liuzhihang.demo.singleton;
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; } }
|
双重检查锁机制(推荐)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package com.liuzhihang.demo.singleton;
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; } }
|