单例模式(Singleton Pattern)

定义:确保某个类只有一个实例,并且自行实例化并向整个体系提供这个实例

需求:保证对象只创建一次

场景:线程池、缓存、日志对象、对话框等常被设计为单例。

Singleton 通过构造方法限定 private 避免类在外部被实例化,在同一个虚拟机范围内,Singleton 的实例只能通过 getInstance 访问。

事实上,通过 Java 的反射机制能够实例化构造函数为 private 的类,基本是上所有的单例都失效。

优点:减少了内存的消耗,重用。

单例通用代码01:(饿汉式)

public class Singleton {

    private static final Singleton singleton = new Singleton();

    private Singleton(){
} public static Singleton getInstance(){
return singleton;
}
   public void say(){}
}

可能产生多个实例02:(懒汉式)

public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){if(instance == null){
instance = new Singleton();
  }
}
return instance;
}
}

在高并发的情况下,可能在 instance ==null 与 new Singleton 之间产生多例。

解决多例的问题:03(懒汉式)方法上加锁

public class Singleton {
private static Singleton instance = null; private Singleton(){} public static synchronized Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
} public void say(){
//todo something
}
}

使用双检查锁:04(懒汉式)双检查,方法内加锁

public class Singleton {
private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class) {
if(instance==null) {
instance = new Singleton();
}
}
}
return instance;
} public void say(){
//todo something
}
}

饿汉式的单例模式,不会出现线程安全的问题。

懒汉式本身是非线程安全的。

方法上加锁与方法内双检查加锁:方法上加锁,虽然线程安全,但是每次都要同步,会影响性能 99% 的情况下是不需要同步的。

方法内检查2次加锁,确保第一次调用的时候加锁,这样是线程安全的,避免了性能的损耗。

扩展:固定数量的单例

public class ExtSingleton {

    //最大单例个数
private static int maxNumOfSingleton = 2; //单例名称
private static ArrayList<String> nameList = new ArrayList<>(); //单例集合
private static ArrayList<ExtSingleton> singletons = new ArrayList<>(); private ExtSingleton(){} private ExtSingleton(String name){
nameList.add(name);
} static {
for(int i=0;i<maxNumOfSingleton;i++){
singletons.add(new ExtSingleton("singleton:"+i));
}
} public static ExtSingleton getInstance(){
//todo 获取单例某个对象
return singletons.get(0);
} }

最新文章

  1. bzoj1584--DP
  2. 【CentOS】压缩打包
  3. nginx切割日志
  4. vs------各种错误解决方法
  5. shell的执行顺序问题
  6. delphi 编写一个dos 窗体
  7. HDOJ/HDU 1297 Children’s Queue(推导~大数)
  8. CSU 1559 订外卖
  9. Eclipse 导入项目乱码问题(中文乱码)
  10. C# Best Practices - Creating Good Methods
  11. 使用spring-data-redis操作redis
  12. replace深入
  13. L2-014 列车调度 (25 分)
  14. ssh命令详解
  15. 编写高质量代码:改善Java程序的151个建议 --[106~117]
  16. Unity StreamingMipmaps 简单测试
  17. docker学习笔记-安装
  18. vue-loader v15、vue-loader v14及之前版本,配置css modules的区别
  19. JS怎样捕获浏览器关闭时间弹出自定义对话框
  20. weblogic 初始化

热门文章

  1. Oracle12c Client安装出现&quot;[INS-30131]&quot;错误“请确保当前用户具有访问临时位置所需的权限”解决办法之完整版
  2. 这个开挂一般的工具,承包你所有的PPT
  3. jupyter notebook 小笔记
  4. 详解一个ThreadLocal 的谜题
  5. 登录之md5加密
  6. 为什么我希望用C而不是C++来实现ZeroMQ
  7. 20165304 实验二 Java面向对象程序设计
  8. linux配置sphinx
  9. FB4.6项目迁移到4.7时 embed报错问题
  10. 基于MFC的OpenGL程序&lt;转&gt;