单例设计模式Singleton

单例设计模式Singleton

存在意义

  • 有些对象的创建消耗时间和内存是非常大的,恰恰好这些对象在我们的应用中只需要使用 1 个,如果不能得到控制,会造成资源的浪费。例如线程池、数据库连接池,一个应用程序中,我们只需要有 1 个这样的大对象。

单例模式的两种写法:懒汉式和饿汉式

说明

  • 饿汉式:在程序启动或单件模式类被加载的时候,单件模式实例就已经被创建。(线程安全)
  • 懒汉式:当程序第一次访问单件模式实例时才进行创建。(线程不安全)

如何选择

  • 如果单件模式实例在系统中经常会被用到,饿汉式是一个不错的选择。

  • 如果单件模式在系统中会很少用到或者几乎不会用到,那么懒汉式是一个不错的选择。

懒汉式

/**
 * 单例懒汉式:当需要用到的时候才会创建实例,缺点:线程不安全
 * 
 * @title
 * @description
 * @since JDK1.8
 */
public class SingleTon {

    private static SingleTon single;

       // 构造器私有化,不能在类的外部随意创建对象
    private SingleTon() {

    }

    //重点:同步不要加在方法上,加在可能发生线程不安全的地方(写操作而不是读操作)
    public static SingleTon getSingleTon() {
        if (single == null) {
            // System.out.println("hello");
            synchronized (SingleTon.class) {
                if (single == null)
                    single = new SingleTon();
            }
        }
        return single;
    }

}

饿汉式

/**
 * 单例模式饿汉式:class文件被加载的时候创建实例,缺点:内存消耗大
 * 
 * @title
 * @description
 * @since JDK1.8
 */
public class SingleTon1 {

    private static SingleTon1 single = new SingleTon1();

    private SingleTon1() {

    }

    public static SingleTon1 getSingleTon1() {
        return single;
    }

}

测试类

/**
 * 单例测试类
 * @title
 * @description
 * @since JDK1.8
 */
public class Main {

    public static void main(String[] args) {
        // // 懒汉测试
        // SingleTon single1 = SingleTon.getSingleTon();
        // SingleTon single2 = SingleTon.getSingleTon();
        // System.out.println(single1 == single2);
        // // 饿汉测试
        // SingleTon1 single3 = SingleTon1.getSingleTon1();
        // SingleTon1 single4 = SingleTon1.getSingleTon1();
        // System.out.println(single3 == single4);

        // 多线程验证懒汉式
        // for (int i = 0; i < 10; i++) {
        // Runnable run = new Runnable() {
        // @Override
        // public void run() {
        // SingleTon single5 = SingleTon.getSingleTon();
        // System.out.println(single5);
        // }
        // };
        // Thread t = new Thread(run);
        // t.start();
        // }

        Runnable run = () -> {
            //懒汉式多线程测试
            SingleTon single5 = SingleTon.getSingleTon();
            System.out.println(single5);
        };

        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(run);
            t.start();
        }
    }
}

扩展

  • 单例模式用途:
    单例模式属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用。
    单例模式能够保证某一类型对象在系统中的唯一性,即某类在系统中只有一个实例。它的用途十分广泛,打个比方,我们开发了一个简单的留言板,用户的每一次留言都要将留言信息写入到数据库中,最直观的方法是没次写入都建立一个数据库的链接。这是个简单的方法,在不考虑并发的时候这也是个不错的选择。但实际上,一个网站是并发的,并且有可能是存在大量并发操作的。如果我们对每次写入都创建一个数据库连接,那么很容易的系统会出现瓶颈,系统的精力将会很多的放在维护链接上而非直接查询操作上。这显然是不可取的。
    如果我们能够保证系统中自始至终只有唯一一个数据库连接对象,显然我们会节省很多内存开销和cpu利用率。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值