Easy单例模式

来源:互联网 发布:西英格兰大学 知乎 编辑:程序博客网 时间:2024/05/17 23:09

在学习单例模式前,不妨问自己几个问题:单例模式是怎么来的,单例模式怎么去用?

单例模式是怎么来的?

这就从设计模式起源开始,他是在实际实践中遇到类似情况可以通用经验所得到的总结,一般在其他模块或者方法多次调用类对象,也就是公共模块,用单例模式可以减少内存的消耗。

单例模式怎么去用?

那这个容易,然后很快不到一分钟写完了。

 1 public class singleTonEx01 { 2  3     private static singleTonEx01 singleTon; 4  5     public static void main(String args[]) { 6         singleTonEx01 test1=singleTonEx01.getInstance(); 7         test1.CommonMethod(); 8     } 9 10     // 防止使用new构造函数实例化对象11     private singleTonEx01() {12 13     }14 15     public static singleTonEx01 getInstance() {16         if(null==singleTon)17             singleTon=new singleTonEx01();18         return singleTon;19     }20     21     public void CommonMethod() {22         System.out.println(getClass().getName());23     }24 25 }
View Code

但这里会有问题,啥问题呢?单线程中是没问题,但是多线程会出现问题,假设两个多线程A与B,A与B同时判断singleTon不为空,那会创建两次,那对于这个问题需要使用同步锁去解决了,下面改造下代码。

public class singleTonEx01 {    private static singleTonEx01 singleTon;    public static void main(String args[]) {        singleTonEx01 test1 = singleTonEx01.getInstance();        test1.CommonMethod();    }    // 防止使用new构造函数实例化对象    private singleTonEx01() {    }    public static singleTonEx01 getInstance() {        synchronized (singleTonEx01.class) {            if (null == singleTon)                singleTon = new singleTonEx01();        }        return singleTon;    }    public void CommonMethod() {        System.out.println(getClass().getName());    }}
View Code

这还不是最好的方法,如果是这样的话每个线程都会使用同步锁代码块,使用同步锁其实是消耗资源的,因此,可以再改进下,在外面锁再加个判断,这样一来提高了效率。(推荐这种写法1)

另外,补充一下,实例变量加上volatile的意义。

创建对象可以分解为如下的3行伪代码memory=allocate(); //1:分配对象的内存空间ctorInstance(memory); //2:初始化对象instance=memory; //3:设置instance指向刚分配的内存地址上面3行代码中的2和3之间,可能会被重排序导致先3后2;

public class singleTonEx01 {    private volatile static singleTonEx01 singleTon;    public static void main(String args[]) {        singleTonEx01 test1 = singleTonEx01.getInstance();        test1.CommonMethod();    }    // 防止使用new构造函数实例化对象    private singleTonEx01() {    }    public static singleTonEx01 getInstance() {        if (singleTon == null) {            synchronized (singleTonEx01.class) {                if (null == singleTon)                    singleTon = new singleTonEx01();            }        }        return singleTon;    }    public void CommonMethod() {        System.out.println(getClass().getName());    }}
View Code

其实还有另外两种方法,一种是不管有没有调用都实例化(俗称恶汉式),另一种是静态内部类的方法(推荐这种写法2),线程安全而且高效

public class singleTonEx02 {    private   static final singleTonEx02 singleTon=new singleTonEx02();    public static void main(String args[]) {        singleTonEx02 test1 = singleTon;        test1.CommonMethod();    }    // 防止使用new构造函数实例化对象    private singleTonEx02() {    }        public static singleTonEx02 getIntance() {        return singleTon;    }         public void CommonMethod() {        System.out.println(getClass().getName());    }}
View Code
public class singleTonEx03 {    private static class SingleNBClass {        private final static singleTonEx03 singleTonEx03=new singleTonEx03();            }    public static void main(String args[]) {        singleTonEx03 test1 = singleTonEx03.getIntance();        test1.CommonMethod();    }    // 防止使用new构造函数实例化对象    private singleTonEx03() {    }    public static final singleTonEx03 getIntance() {        return SingleNBClass.singleTonEx03;    }    public void CommonMethod() {        System.out.println(getClass().getName());    }}
View Code

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 全民k歌有杂音怎么办 录歌换气声很大怎么办 网易云没有的歌怎么办 qq空间给封了怎么办 酒店住最后一间怎么办 妻子起诉离婚丈夫不离怎么办 老婆对我没感情怎么办 老婆要跟我离婚怎么办 眼睛里进了沙子怎么办 耳塞孔进沙子了怎么办 斜挎包链子长了怎么办 爱上大15岁大叔怎么办 老板不给发工资怎么办 4个月婴儿感冒了怎么办 9个月宝宝感冒了怎么办 婆婆去世了我该怎么办 腰疼得睡不着觉怎么办 长期抱孩子腰疼怎么办 抱孩子累的腰疼怎么办 带孩子带的腰疼怎么办 生完孩子后便秘怎么办 生完宝宝下面松怎么办 坐完月子后腰疼怎么办 生完宝宝腰疼怎么办 生完小孩后腰痛怎么办 生完小孩痔疮痛怎么办 生完孩子阴松弛怎么办 生完孩子乳房松弛怎么办 生完宝宝后腰痛怎么办 顺产的过程很疼怎么办 生完孩子想离婚怎么办 刨腹产后胃胀气怎么办 月子里宝宝涨肚怎么办 肠鸣放屁多便秘怎么办 趴着睡觉胃胀气怎么办 备孕三个月了还是没怀上怎么办 月子里喂奶腰疼怎么办 生完孩子子宫疼怎么办 记账凭证写错了怎么办 饥荒精神值为0怎么办 抓不住温暖我能怎么办