参考: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  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

三、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静态内部类

 

原文地址:http://www.cnblogs.com/q994321263/p/16930262.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性