前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【AI赋能:单例模式在智能编程中的实践与优化】

【AI赋能:单例模式在智能编程中的实践与优化】

作者头像
ImAileen
发布2024-12-27 08:30:49
发布2024-12-27 08:30:49
9900
代码可运行
举报
运行总次数:0
代码可运行

前言

本文主要讲解设计模式的创建模式中的单例模式的饿汉式,它是在类加载时创建对象,它的实现方式有两种,一种是通过静态变量来实现,另一种是通过静态代码块来实现;以及饿汉式的两种实现方式,一种是线程不安全实现方式,另一种是通过通过synchronized关键字实现的线程安全方式

单例模式

  • 单例模式结构:
    • 单例类:只能创建一个实例的类
    • 访问类:使用单例类。

饿汉式

饿汉式:类加载就会导致改单实例对象被创建。

实现方式①:通过静态变量实现
  • 1.创建私有构造方法使得外界无法访问此构造方法,外界无法访问此私有构造方法就无法创建其对象
  • 2.在本类中创建本类对象,通过private关键字不让外界直接访问
  • 3.提供一个公共的访问方式,让外界获取该对象(由于外界不能创建本类对象所以无法调用非静态的成员方法,所以这个方法要用static修饰变成静态的),此外,静态无法访问非静态的东西,所以刚刚第二步创建的对象要变成静态的。
具体代码
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.hungrystyle.staticcode;

/**
 * 饿汉式:静态成员变量
 */
public class Singleton {

    //1.私有构造方法的创建-> 使得外部无法创建多个该类对象
    private Singleton(){

    }

    //2.在本类中创建本类的对象-> 确保全局只有一个实例
    private static Singleton singleton = new Singleton();

    //3.提供一个公共的访问方式,让外界获取该对象
    public static Singleton getSingleton(){
        return  singleton;
    }
}
测试类
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.hungrystyle.staticcode;

public class Test {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getSingleton();
        Singleton singleton2 = Singleton.getSingleton();

        //判断两次获取的Singleton对象是否是同一个对象
        System.out.println(singleton1 == singleton2);
    }
}
  • 私有方法通过类名去访问,
  • 结果为true:表示我们通过类名调用的getSingleton指向的是同一个对象,也能反映出Singleton这个类只能创建一个对象。

实现方式②:通过静态代码块实现
具体代码
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.hungrystyle.staticmethod;

/**
 * 饿汉式:静态代码块
 */
public class Singleton {
    //私有构造方法
    private Singleton (){

    }

    //声明Singleton类型的变量
    private static Singleton  singleton;

    //在静态代码块中将对象赋值给刚刚的变量
    static{
        singleton = new Singleton(); 
        //因为这里的是静态代码块,静态只能访问静态,
        // 所以上面的变量也必须是静态的。
    }

    //对外提供获取该类对象的方法
    public static Singleton getSingleton(){
        return singleton;
    }
}
测试类
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.hungrystyle.staticmethod;

public class Test {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getSingleton();
        Singleton singleton2 = Singleton.getSingleton();

        //判断两次获取到的Singleton对象是否是同一个
        System.out.println(singleton1 == singleton2);
    }
}
运行结果
  • 运行结果为:true。说明两次通过类名访问的是同一个对象,它们的内存地址相同。

异同点总结:

  • 区别: 一个是直接创建完之后就赋值了,另一个是先创建然后在静态代码块中进行赋值。
  • 相同点: 两种方式的对象都是随着类的加载而创建的,但这两种方式会造成内存浪费问题,如果我只是对类进行加载的操作并未获取该类对象,若使用饿汉式就会导致该对象一直存储在内存中,一直未被使用,造成内存浪费

懒汉式

懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建。

实现方式①:线程不安全式

对于这种每次调用getSingleton方法时都会重新创建一个对象,这会使得我们在测试类中判断我们通过Singleton类调用这个方法创建的对象的内存地址返回的结果会是false,因为每次都会创建一个新对象。我们可以添加if-else来判断对象是否被创建,如果创建了就返回,没有就创建,使它只创建一次对象,从而满足我们的单例模式。

实现代码
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.lazystyle.Threadunsafe;

public class Singleton {
    //1.私有方法的构造
    private Singleton(){

    }

    //2.声明Singleton类型的变量 singleton
    private static Singleton singleton;

    //3.对外提供访问方式
    public static Singleton getSingleton(){
        //判断singleton是否为nuLL,如果为nuLL,说明还没有创建SingLeton类的对象
        //如果没有,创建一个并返回,如果有,直接返回
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}
测试类
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.lazystyle.Threadunsafe;

public class Test {
    public static void main(String[] args) {
        Singleton mysingleton1 = Singleton.getSingleton();
        Singleton mysingleton2 = Singleton.getSingleton();
        System.out.println(mysingleton1 == mysingleton2);
    }
}
  • 从上面的代码可以看到当我们调用getSingleton()方法获取Singleton类的对时才创建Singleton类的对象,这样就实现了懒加载的效果。当程序运行到判断语句时,假设有线程1和线程2,若线程1在等待,线程2就能获取到CPU的执行权,也会进入到判断里面。但是会出现线程安全问题。
实现方式② (通过添加synchronized关键字变成线程安全式)
实现代码
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.lazystyle.Threadsafe;

public class Singleton {
        //1.私有方法的构造
        private Singleton(){
        }

        //2.声明Singleton类型的变量 singleton
        private static Singleton singleton;

        //3.对外提供访问方式
        public static synchronized Singleton getSingleton(){
            //判断singleton是否为nuLL,如果为nuLL,说明还没有创建SingLeton类的对象
            //如果没有,创建一个并返回,如果有,直接返回
            if(singleton == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }
测试类
代码语言:javascript
代码运行次数:0
复制
package pattern.singleton.lazystyle.Threadsafe;

public class Test {
    public static void main(String[] args) {
        Singleton mysingleton3 = Singleton.getSingleton();
        Singleton mysingleton4 = Singleton.getSingleton();
        System.out.println(mysingleton3 == mysingleton4);
    }
}
  • 当我们加上synchronized关键字的时候,就变成了线程安全式的单例模式,线程2就没法进来获取cpu的执行权,因为它是同步锁,只有等线程1完成了才能执行线程2。

异同点总结:

  • 区别: 一个是线程不安全的方式实现懒加载,一个是通过synchronized实现懒加载的效果的同时,又解决了线程安全问题。但是在getSingleton()方法上添加了synchronized关键字,会导致该方法的执行效果非常低。从上面的代码我们可以看出,出现线程安全问题是在初始化singleton的时候,一旦初始化完成就不存在了。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 单例模式
    • 饿汉式
      • 实现方式①:通过静态变量实现
      • 具体代码
      • 测试类
      • 实现方式②:通过静态代码块实现
      • 具体代码
      • 测试类
      • 运行结果
    • 异同点总结:
    • 懒汉式
      • 实现方式①:线程不安全式
      • 实现代码
      • 测试类
      • 实现方式② (通过添加synchronized关键字变成线程安全式)
      • 实现代码
      • 测试类
    • 异同点总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档