博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我是皇帝我独苗之单例模式
阅读量:7096 次
发布时间:2019-06-28

本文共 2605 字,大约阅读时间需要 8 分钟。

什么是单例模式?

确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。通俗一点就是确保一个类只能产生一个对象,所有对象对他的依赖都是相同的。
单例模式的几种实现方式

  • 懒汉式(线程不安全)

    public class Singleton {      private static Singleton singleton;      private Singleton (){}      public static synchronized Singleton getInstance() {      if (singleton == null) {          singleton = new Singleton();      }      return singleton;      }  }
  • 饿汉式(线程安全)
    public class Singleton {  private static Singleton singleton = new Singleton();  private Singleton (){}  public static Singleton getInstance() {  return singleton;  }  }

单例模式的注意事项

高并发的情况下注意单例模式的线程同步问题,测试代码如下:

public class Emperor {    private static String name = null;    private static Emperor emperor = null;    //限制产生多个对象    private Emperor(String e) {        Emperor.name=e;    }    //通过该方法获得实例对象    public static Emperor getInstance(String e) {        if (emperor == null) {            emperor = new Emperor(e);        }        return emperor;    }    //类中的其他方法尽量使用static    public static void say(String m) {//      Emperor.name=e;        System.out.println("我是:"+ m +", 参见皇帝"+Emperor.name);    }}

package com.zgz.dm.Singleton;public class Minister {    public static void main(String[] args) {        Minister1 minister1 = new Minister1();        Minister2 minister2 = new Minister2();        new Thread(minister1).start();        new Thread(minister2).start();        /*for(int day=0; day<3; day++) {            Emperor emperor = Emperor.getInstance();            emperor.say();        }*/    }}class Minister1 implements Runnable{    private String minister = "王安石";    private String s = "宋神宗1";    @Override    public void run() {        for(int i=0; i<10; i++) {            Emperor emperor = Emperor.getInstance();            emperor.say(s,minister);            try {                Thread.sleep((int)Math.random()*200);            } catch (Exception e) {                e.printStackTrace();            }        }    }}class Minister2 implements Runnable{    private String minister = "苏轼";    private String s = "宋神宗2";    @Override    public void run() {        for(int i=0; i<10; i++) {            Emperor emperor = Emperor.getInstance();            emperor.say(s,minister);            try {                Thread.sleep((int)Math.random()*1000);            } catch (Exception e) {                e.printStackTrace();            }        }    }}

测试结果:
我是皇帝我独苗之单例模式
原因分析:
王安石应该是宋神宗1啊?为啥是宋神宗12呢,就说明内存中存在两个对象。一个线程A执行到 emperor = new Emperor(),但还没有获得对象(对象的初始化需要时间),第二个线程B正在执行,执行到 (emperor == null),线程B获得判断条件为真,于是继续执行。于是A与B都获得了对象,内存中出现了两个对象。
解决办法:
加锁,执行效率低。建议使用饿汉式单例

转载于:https://blog.51cto.com/13416247/2296494

你可能感兴趣的文章
随机字符串生成算法
查看>>
Jenkins重置安全配置
查看>>
mahout0.7 示例运行纪实
查看>>
centos7快速部署ceph
查看>>
git安装和使用案例
查看>>
cisco路由器进入rommon模式
查看>>
awk Tips
查看>>
继承抽象类
查看>>
(摘)Excel 2007查询操作中的函数应用
查看>>
使用SCOM资源工具包来协助MP开发及调试
查看>>
从Linux终端管理进程:10个你必须知道的命令
查看>>
centos7 命令补全
查看>>
JAVA递归中的垃圾回收
查看>>
PyTables Windows平台安装说明
查看>>
Linux crontab定时执行任务 命令格式与详细例子
查看>>
IDC: 2018年智能家居将打破设备孤岛瓶颈
查看>>
Redis的三种启动方式
查看>>
python多线程之线程锁三(同一时间允许多个线程)
查看>>
PinPoint分布式全链路监控
查看>>
【Flume】HDFSSink配置参数说明
查看>>