01.(创建型模式)java设计模式之单例模式

参考:https://blog.csdn.net/liu_da_da/article/details/125425561

一、什么是单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

二、单例的几种实现方式

1.饿汉模式

饿汉式,就是“比较饿”,实例在初始化的时候就要创建好,不管你有没有用到。类加载到内存后,就实例化一个单例,JVM保证线程安全;简单实用,推荐实用!唯一缺点:不管用到与否,类装载时就完成实例化(话说你不用的,你装载它干啥)

public class Singleton {
    private static final  Singleton INSTANCE=new Singleton();
    private Singleton(){};
    public static Singleton getInstance(){return INSTANCE;}
}

 测试用例:

 public static void main(String [] args){
        Singleton m1=Singleton.getInstance();
        Singleton m2=Singleton.getInstance();
        System.out.println(m1==m2);
    }

测试结果:true  

2.懒汉模式

懒汉式就是“比较懒”,就是在用到的时候才去检查有没有实例,如果有则直接返回,没有则新建。案例中保留性能与线程安全的双重检索模式。

2.1双重检索模式

//双重检索模式
public class Singleton {
    private static volatile  Singleton INSTANCE2;
    private Singleton(){};
    
    public static Singleton getInstance2(){
        if(INSTANCE2==null){
            synchronized (Singleton.class){
                if(INSTANCE2==null){
                    INSTANCE2=new Singleton();
                }
            }
        }
        return INSTANCE2;
    }
}

2.2静态内部类

//私有静态内部类
public class Singleton {
    private Singleton(){};
    public static Singleton getInstance3(){return LazyHolder.INSTANCE;}
    //私有静态内部类
    private static  class LazyHolder{
        private static final  Singleton INSTANCE=new Singleton();
    }
}

测试用例:

   //测试方式
        for (int i=0;i<100;i++){
            new Thread(()->{
                System.out.println(Singleton.getInstance2().hashCode());
            }).start();
        }

测试结果:100 个都是1120223167

3.枚举

优点:内存中只存在一个对象实例,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。

缺点:当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰

public enum SingletonEnum {
    INCTANCE;
    public void method(){
        System.out.println("枚举类中定义方法!");
    }
}

测试用例:

public static void main(String [] args){
    //测试方式
    for (int i=0;i<100;i++){
        new Thread(()->{
            System.out.println(SingletonEnum.INCTANCE.hashCode());
        }).start();
    }
}

测试结果:100 个都是1484015707

4.如何选择

如果对象不⼤,且创建不复杂,直接⽤饿汉的⽅式即可。其他情况则采⽤懒汉实现⽅式

三、JAVA知识点

3.1synchronized

 参考:https://www.jb51.net/article/226912.htm

Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

【修饰一个代码块】一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞

     Synchronized作用于整个方法的写法

//直接作用在方法上
public synchronized void method1() {
    System.out.println("method1!");
}
//封装代码块
public void method2() {
    synchronized(this) {
        System.out.println("method2!");
    }
}

 

  • 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
  • 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
  • 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

缺点:在分布式环境中,不能保证线程的安全。

3.2volatile

参考:(https://www.cnblogs.com/fhblikesky/p/13692645.html

volatile 是 Java 中的关键字,是一个变量修饰符,被用来修饰会被不同线程访问和修改的变量。

【可见性】可见性是指多个线程访问同一个变量时,其中一个线程修改了该变量的值,其它线程能够立即看到修改的值。

【原子性】volatile 只保证单次读/写操作的原子性,对于多步操作,volatile 不能保证原子性。

3.2静态内部类

在一个类中创建另外一个类,叫做成员内部类。这个成员内部类可以静态的(利用static关键字修饰),也可以是非静态的。使用方式参考2.2静态内部类

 

posted @   冰融心  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示