单例模式和多线程

本贴最后更新于 2808 天前,其中的信息可能已经斗转星移

单例模式是 23 个设计模式中比较简单,也是最常用的模式之一,虽然简单,但在多线程并发访问时如果不注意一些使用细节,会引发意想不到的 bug。

单例模式

定义:保证一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。
类图:待完成
优点:

  • 减少内存开支
  • 减少性能开销
  • 避免对资源的多重占用
  • 提供和共享全局访问量
    缺点:
  • 扩展性差
  • 测试不方便
  • 单例模式和单一职责莫设计原则向冲突

单例的变相形式

饿汉模式

public class EagerSingleton { private static EagerSingleton singleton=new EagerSingleton(); private EagerSingleton(){ } public static EagerSingleton getSingleton(){ return singleton; } }

懒汉模式

该代码采用了 DCL 双锁检测(double checked locking),避免了因为多线程并发下可能出现的异常

public class LazySingleton { private volatile static LazySingleton singleton; private LazySingleton(){ } public static LazySingleton getSingleton() throws InterruptedException { if (singleton != null) { } else { Thread.sleep(3000); synchronized (LazySingleton.class) { if (singleton == null) { singleton = new LazySingleton(); } } } return singleton; } }

测试类:

public class MyThread extends Thread{ @Override public void run() { super.run(); System.out.println("EagerSingleton"+EagerSingleton.getSingleton().hashCode()); try { System.out.println("LazySingleton"+LazySingleton.getSingleton().hashCode()); } catch (InterruptedException e) { e.printStackTrace(); } } } public class Test { public static void main(String[] args) { MyThread t1=new MyThread(); MyThread t2=new MyThread(); MyThread t3=new MyThread(); MyThread t4=new MyThread(); t1.start(); t2.start(); t3.start(); t4.start(); } }

运行结果

EagerSingleton908288934 EagerSingleton908288934 EagerSingleton908288934 EagerSingleton908288934 LazySingleton1515217202 LazySingleton1515217202 LazySingleton1515217202 LazySingleton1515217202

可以看到 hash 值相同,证明了我们的结论,试着把双重检查中的判空代码去掉,再运行下结果,你会发现单例失效了!

  • 设计
    118 引用 • 797 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...