前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【趣学程序】设计模式之单例模式

【趣学程序】设计模式之单例模式

作者头像
趣学程序-shaofeer
发布2019-07-27 18:28:28
3710
发布2019-07-27 18:28:28
举报
文章被收录于专栏:upuptop的专栏

单例模式

单例模式用来创建的对象可以确保系统中只产生一个示例。主要有以下两种好处:1.对于频繁使用的对象可以省略创建对象所花费的时间 2.由于new操作的次数减少,对系统内存的使用频率也会降低。将减轻GC压力。缩短GC停顿时间。

创建单例模式

代码语言:javascript
复制
public class SingleClassDemo {
    //第一种方式 直接创建对象 需要时直接返回    public static SingleClassDemo sSingleClassDemo = new SingleClassDemo();
    private SingleClassDemo() {        System.out.println("创建单例对象");    }

    public static SingleClassDemo getInstance() {        return sSingleClassDemo;    }

    // 该类中的其他静态方法    //public static String otherMethod() {    //    return "otherMethod otherMethod!";    //}
}
/***    测试类*/public class TestSingleClassDemo {    @Test    public void testInstance() {
        SingleClassDemo instance = SingleClassDemo.getInstance();        System.out.println(instance);        //打印结果:创建单例对象  top.wintp.demo.SingleClassDemo@50486d1d    }}

如上述代码就是单例模式的一种简单的实现方式。试想我们这种实现方式会有什么问题呢?当该类中存在其他的静态方法的时候,我们直接调用该类的其他静态方法,也会创建该类的对象,这是我们不想得到的结果

调用示例:

代码语言:javascript
复制
public class TestSingleClassDemo {    @Test    public void testInstance() {        //当调用该类的其他方法的时候,会初始化该类该类的静态变量 创建对象        String string = SingleClassDemo.otherMethod();        System.out.println(string);        //打印结果:创建单例对象        cotherMethod otherMethod!    }}

单例模式优化一(懒加载模式)

修改创建单例对象的时机,当有需要的时候再去创建对象。

代码语言:javascript
复制
public class LazSingleClassDemo {
    private static LazSingleClassDemo mLazSingleClassDemo = null;
    private LazSingleClassDemo() {        System.out.println("创建懒加载模式的对象");    }
    public static LazSingleClassDemo getmLazSingleClassDemo() {
        if (mLazSingleClassDemo == null) {            mLazSingleClassDemo = new LazSingleClassDemo();        }
        return mLazSingleClassDemo;    }
    public static String otherMehod() {
        return "otherMehod otherMehod";    }}


public class TestSingleClassDemo {    @Test    public void testInstance() {
        //    懒加载模式        //在懒加载模式中 调用该类的其他方法并不会创建该类的对象        String string = LazSingleClassDemo.otherMehod();        System.out.println(string);        //打印结果:otherMehod otherMehod    }}

当多线程并发时,懒加载模式就可能会出现,当前线程检测为null,第二个线程检测为null,同时创建两个对象的情况。那就违背了单例的原则。

调用示例:

代码语言:javascript
复制
public class TestSingleClassDemo {    @Test    public void testInstance() {        //    懒加载模式的线程并发问题        new Thread("t1") {            public void run() {                LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(lazSingleClassDemo);            }        }.start();        new Thread("t2") {            public void run() {                LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(lazSingleClassDemo);            }        }.start();        new Thread("t3") {            public void run() {                LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(lazSingleClassDemo);            }        }.start();        new Thread("t4") {            public void run() {                LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(lazSingleClassDemo);            }        }.start();
        new Thread("t5") {            public void run() {                LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(lazSingleClassDemo);            }        }.start();

        /*        打印结果如下:
        创建懒加载模式的对象        创建懒加载模式的对象        t2        top.wintp.demo.LazSingleClassDemo@475f260c        t1        top.wintp.demo.LazSingleClassDemo@55b9171e        t3        top.wintp.demo.LazSingleClassDemo@475f260c        t4        top.wintp.demo.LazSingleClassDemo@475f260c        t5        top.wintp.demo.LazSingleClassDemo@475f260c         */    }}

单例模式优化二(懒加载模式线程并发问题)

使用同步方法避免多线程并发。

代码语言:javascript
复制
public class LazSingleSyncClassDemo {
    private static LazSingleSyncClassDemo mLazSingleClassDemo = null;
    private LazSingleSyncClassDemo() {        System.out.println("创建懒加载模式同步方法的对象");    }
    //使用synchronized 关键字    public static synchronized LazSingleSyncClassDemo getmLazSingleClassDemo() {
        if (mLazSingleClassDemo == null) {            mLazSingleClassDemo = new LazSingleSyncClassDemo();        }
        return mLazSingleClassDemo;    }
    public static String otherMethod() {
        return "otherMethod otherMethod";    }}

如上代码,再次进行多线程进行调用就不会出现创建多个对象的结果 线程安全避免不了的就是性能会降低。下面就是线程同步与线程不同的测试程序执行时长

代码语言:javascript
复制
public class TestSingleClassDemo {    @Test    public void testInstance() {        long beginTime = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo();        }        long endTime = System.currentTimeMillis();
        System.out.println(endTime - beginTime);        //懒加载模式 不同步方法 用时间:2

        beginTime = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            LazSingleSyncClassDemo lazSingleClassDemo = LazSingleSyncClassDemo.getmLazSingleClassDemo();        }        endTime = System.currentTimeMillis();
        System.out.println(endTime - beginTime);        //懒加载模式 同步方法 用时间:5
    }}

单例模式优化三(使用静态内部类进行优化)

代码语言:javascript
复制
public class EndSingleClassDemo {
    private static EndSingleClassDemo mLazSingleClassDemo = null;
    private EndSingleClassDemo() {        System.out.println("创建懒加载模式的对象");    }

    /**     * 静态内部类     */    private static class EndSingleClassDemoHolder {        private static EndSingleClassDemo mLazSingleClassDemo = new EndSingleClassDemo();    }
    public static EndSingleClassDemo getmLazSingleClassDemo() {
        return EndSingleClassDemoHolder.mLazSingleClassDemo;    }
    public static String otherMehod() {
        return "otherMehod otherMehod";    }}

public class TestSingleClassDemo {    @Test    public void testInstance() {        new Thread("t1") {            public void run() {                EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(endSingleClassDemo);            }        }.start();        new Thread("t2") {            public void run() {                EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(endSingleClassDemo);            }        }.start();        new Thread("t3") {            public void run() {                EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(endSingleClassDemo);            }        }.start();        new Thread("t4") {            public void run() {                EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(endSingleClassDemo);            }        }.start();        new Thread("t5") {            public void run() {                EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();                System.out.println(this.getName());                System.out.println(endSingleClassDemo);            }        }.start();

        long beginTime = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo();        }        long endTime = System.currentTimeMillis();
        System.out.println("用时间:" + (endTime - beginTime));
        /*        打印结果如下:
        创建懒加载模式的对象        t1        t2        t3        top.wintp.demo.EndSingleClassDemo@4dbb3e34        top.wintp.demo.EndSingleClassDemo@4dbb3e34        top.wintp.demo.EndSingleClassDemo@4dbb3e34        t4        top.wintp.demo.EndSingleClassDemo@4dbb3e34        t5        top.wintp.demo.EndSingleClassDemo@4dbb3e34        用时间:1         */
    }}

一个优秀的程序员,不仅要会编写程序,更要学会编写高质量的程序。事虽难,做则成;路虽远,行则至。所涉及的代码:https://github.com/upuptop/WeChatQuXueChengXu

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 趣学程序 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例模式
  • 创建单例模式
  • 单例模式优化一(懒加载模式)
  • 单例模式优化二(懒加载模式线程并发问题)
  • 单例模式优化三(使用静态内部类进行优化)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档