单例模式--投篮时最好保持一种姿势

本文深入探讨了单例模式的设计理念,介绍了如何通过私有构造函数确保一个类仅有一个实例,并提供了一个全局访问点。讨论了单例模式在多线程环境下的实现挑战及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1)概述
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,提供一个访问它的全局访问点。核心是创建私有的构造函数。可拓展到有限个实例。
相似情形
1.家兴作为一个资深野球场上的投手,球场全场无死角,投篮技术可是真的很牛逼呀,但是细看他的投篮姿势都是一种,无论在哪一个角度都是一样。下面个人去分析一下家兴的投篮姿势,投篮可是千变万化,每一个位置、高度,加速度都是不一样的,但是家兴很聪明知道以一种投篮方式去实现,这样对他的投篮影响也是最小。因为无论外界因素怎么变,家兴只需要调控力度,和弧度就能完成每一个漂亮的投篮。
2.现在计划生育已经放松了,以前实行计划生育一个家庭只能生育一个孩子,把责任交给家庭,让家庭去执行,无论外界什么要求,只能生一个。

2)问题
1.对于某一些要求,我们只要求一个对象,任何需要来调用允许一个唯一对象,但是每次实例化都会产生新的对象,应该怎么去实现?

3)解决方案
通过建立私有的构造函数,不让外界初始化,定义唯一的私有静态初始化变对象,创建一个公共方法获取已经初始化的唯一静态的对象。

4)使用场景
对于哪些只要求产生一个对象,不允许再产生其它的对象。

5)结构
Singleton:单例类,通过使用private的构造函数,确保了在一个应用中只产生一个实例,并且是自行实例化。
Client:客户端类,通过调用Singleton类的公共方法来获取唯一实例化对象。

6)单例模式XML图
这里写图片描述

7)代码实现

public class Singleton {
    private static Singleton singleton;
    private Singleton(){

    }
    public static Singleton getSingleton(){
        if(singleton==null){
            singleton =  new Singleton();
        }
        return singleton;
    }

    public static void operation(){
        System.out.println(singleton);
    }

}

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Singleton singleton = Singleton.getSingleton();
        Singleton singleton1 = Singleton.getSingleton();
        singleton.operation();
        singleton1.operation();
    }

}

程序执行结果
com.yatming.singleton.Singleton@3a18cecd
com.yatming.singleton.Singleton@3a18cecd

8)单例模式的优点
1.保证唯一的实例
2.由于是因为Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问它。

9)针对多线程时的单例
问题:java多线程的情况下,对于同时访问Singleton类的时候可能getSingleton方法的时候存在创建多个实例,对于这种情况该怎么去解决呢?
解决办法,对于当前线程进行锁定,让后来的的线程在外面等待,直到该实例已经被建立好
用synchronized关键子对getSingleton锁定,只有当前线程执行完毕后,下一个线程才能执行调用

但是同步getSingleton的做法可是会拖垮性能,该怎么去处理?
1.如果你的程序允许你忽略getSingleton()造成性能的负担,你可以不用理会这件事。但是你要考虑到这样一个问题,同步一个方法可能会造成程序执行效率降低100倍。特别是getSingleton方法如果在频繁使用,你就要很重视去看待这样一个问题。
2.如果应用程序总是创建并使用单件案例,或者在创建和运行时方面的负担不太繁重,你可能想要迫切创建此单件,如下所示:

private static Singleton singleton = new Singleton ();

public static Singleton getSingleton(){
    return singleton;
}

利用这个做法我们依赖JVM在加载这个类时马上创建此唯一的单件案例。JVM保证在任何线程访问singleton静态变量,一定会先创建此实例。
那么如果这样一个实例一直没有被使用,创建一个实例会占用空间,该怎么去完善呢?
3.如果在调用getSingleton方法的时候,首先检查是否实例化,如果还没有创建,我们才去让它实现同步。这样一来,这是满足我们的效果。

public class Singleton(){
    private volatitle static Singleton singleton;
    private Singleton(){
    }
    public static Singleton getSingleton(){
        if(singleton == null){
            sysnchronized (Singleton.class){
                if(singleton==null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
}

}

这个方法就是双重检查加锁(double-check locking)

还有一个问题的是:
如果程序有两个类加载器,就可能各自创建自己的单件实例;这是一般采取的解决办法是自行指定一个类加载器,并指定同一个类加载器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值