java实现单例模式

/**
 * 单例模式的特点
 *
 * 1. 单例模式只能有一个实例。
 *
 * 2. 单例类必须创建自己的唯一实例。
 *
 * 3. 单例类必须向其他对象提供这一实例。
 *
 *
 */

/**单例类和静态类的对比
 * 1. 单例可以继承和被继承,方法可以被override,而静态方法不可以。
 *
 * 2. 静态方法中产生的对象会在执行后被释放,进而被GC清理,不会一直存在于内存中。
 *
 * 3. 静态类会在第一次运行时初始化,单例模式可以有其他的选择,即可以延迟加载。
 *
 * 4. 基于2, 3条,由于单例对象往往存在于DAO层(例如sessionFactory),如果反复的初始化和释放,则会占用很多资源,而使用单例模式将其常驻于内存可以更加节约资源。
 *
 * 5. 静态方法有更高的访问效率。
 *
 * 6. 单例模式很容易被测试。
 *
 * 几个关于静态类的误解:
 *
 * 误解一:静态方法常驻内存而实例方法不是。
 *
 * 实际上,特殊编写的实例方法可以常驻内存,而静态方法需要不断初始化和释放。
 *
 * 误解二:静态方法在堆(heap)上,实例方法在栈(stack)上。
 *
 * 实际上,都是加载到特殊的不可写的代码内存区域中。
 *
 * 静态类和单例模式情景的选择:
 *
 * 情景一:不需要维持任何状态,仅仅用于全局访问,此时更适合使用静态类。
 *
 * 情景二:需要维持一些特定的状态,此时更适合使用单例模式。
 */

/**
 * lazyloading也就是延迟加载的意思
 * 延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。
 * 延迟加载也称为惰性加载,即在长网页中延迟加载图像。用户滚动到它们之前,视口外的图像不会加载。
 * 这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。
 *在某些情况下,它还可以帮助减少服务器负载。
 * 对于前端后台来说  lazyloading都有着应用
 *
 * 但是延迟加载对于后台开发来说,也有着巨大的弊端
 * 第一,延迟加载搞不好就容易导致N+1 select问题,性能反而不能保障
 * 	第二,延迟加载一般是在ORM(对象关系映射)中采用字节码增强方式来实现,这种方式处理后的对象往往会导致对象序列化失效,而在大型web应用中一般都会采用 独立的缓存架构,一但应用系统引入独立的缓存系统对应用数据对象进行缓存,采用延迟加载后的对象序列化将失效,导致缓存失败。
 * 	第三,ORM中的延迟加载将业务对象的加载关系搞得不清不楚,如果某天想换ORM,那么还得针对不同的ORM处理延迟加载关系,即使不还ORM后来人想理解加载关系也会很头疼。
 * 	第四,延迟加载目的是一方面是对了使应用只加载必要的数据,减少数据传输量,提高查询速度。另一方面,为了减轻数据库的进行不必要查询而进行运行增加的压力,避免一次性进行过多的查询,减少系统消耗。对于第一个问题,通过必要的缓存一般可以解决,对于这点系统消耗一般还是可以承受;对于第二个问题,通过在业务层进行单表查询配合必要的索引一般也是不存在问题的。
 * 	第五,从另外一方面考虑,ORM需要承担的仅仅是O R M,和事务、缓存等特性一样,它们应该由其他更有资格的家伙来承担,不需要搞那么负载,否则对于以后的底层扩展,那可是一个艰巨的工作。
 * 	这段文字参考自 https://blog.csdn.net/sun11462/article/details/43369985
 */


public class Singleton {
    //懒汉式
    //可以lazyloading 但有一个巨大的问题就是线程不安全,如果多个线程同时调用,则会创建出许多对象
    private  static Singleton singleton;
    private  Singleton(){}
    public static Singleton getSingleton(){
        if(singleton==null){
            return singleton = new Singleton();
        }
        return singleton;
    }
    //线程安全
   // 然而并发其实是一种特殊情况,大多时候这个锁占用的额外资源都浪费了,这种打补丁方式写出来的结构效率很低。
   public static synchronized Singleton getSingleton1(){
       if(singleton==null){
           return singleton = new Singleton();
       }
       return singleton;
   }
}
//饿汉式,直接在本类创建了一个对象,用的时候直接loading
class SingletonDemo{
    private static SingletonDemo singletonDemo = new SingletonDemo();
    private SingletonDemo(){}
    public static SingletonDemo getSingletonDemo(){
        return singletonDemo;
    }

}
//静态类内部加载
/**
 * 使用内部类的好处是,静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,
 * 达到了类似懒汉模式的效果,而这种方法又是线程安全的,不会说创建多个对象
 */
class  StaticSingleton{
    private static class StaticSingletonHandler{
    private static StaticSingleton staticSingleton = new StaticSingleton();
    }
    private StaticSingleton(){ }
    public static StaticSingleton getStaticSingleton(){
        return StaticSingletonHandler.staticSingleton;
    }

}


//优雅的写法  枚举
enum SingletonD{
    Instance;
    public void saying(){
        System.out.println("枚举构建单例模式");
    }
}
//双重校验锁法

/**
 * 双锁机制   第一个锁 锁引用,第二个锁 锁实例化
 * 1.线程A访问getInstance()方法,因为单例还没有实例化,所以进入了锁定块。
 *
 * 2.线程B访问getInstance()方法,因为单例还没有实例化,得以访问接下来代码块,而接下来代码块已经被线程1锁定。
 *
 * 3.线程A进入下一判断,因为单例还没有实例化,所以进行单例实例化,成功实例化后退出代码块,解除锁定。
 *
 * 4.线程B进入接下来代码块,锁定线程,进入下一判断,因为已经实例化,退出代码块,解除锁定。
 *
 * 5.线程A初始化并获取到了单例实例并返回,线程B获取了在线程A中初始化的单例。
 *
 * 双重校验锁法是线程安全的,并且,这种方法实现了lazyloading。
 * 此段代码参考自https://www.cnblogs.com/cielosun/p/6582333.html
 */
class DoubleSingletonDemo {
    private volatile static DoubleSingletonDemo instance;
    private DoubleSingletonDemo(){
        System.out.println("Singleton is loading");
    }
    public static DoubleSingletonDemo getInstance(){
        if(instance==null){
            synchronized (DoubleSingletonDemo.class){
                if(instance==null){
                    instance=new DoubleSingletonDemo();
                }
            }
        }
        return instance;
    }
}



class  Test{


    public static void main(String[] args) {
        SingletonDemo singletonDemo = SingletonDemo.getSingletonDemo();
        System.out.println(singletonDemo);
        //枚举调用单例(优雅)
        SingletonD.Instance.saying();
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值