设计模式-单例

特点

  • 系统内有且只有一个实例对象;
  • 单例类的构造方法为私有的,自己持有自己的一个实例对象;
  • 开放获取实例对象的方法;

分类

单例模式主要可分为饿汉式、饱汉式、枚举式、内部类、容器式;测试代码均采用多线程测试方式。

饿汉式

在类加载时,创建一个实例,当外部获取时,直接返回创建的实例。这种方式占用了一定的内存空间、节约了在使用时创建对象的时间和资源消耗。也不用担心线程安全的问题。

public class HungrySingleton {

    private HungrySingleton(){}

    private static final HungrySingleton INSTANCE = new HungrySingleton();

    public HungrySingleton getInstance(){
        return INSTANCE;
    }
}

测试代码

	@Test
    public void testHungrySingleton() throws InterruptedException {
		ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.submit(() ->{
                HungrySingleton instance = HungrySingleton.getInstance();
                log.info("线程 {} 获取到的实例: {}",Thread.currentThread().getName(),instance);
            });
        }
    }

说明:创建10个线程分别获取HungrySingleton实例,进而知晓获取到的10个实例对象的内存地址:

2021-03-04 13:24:16.717  INFO 8428 --- [pool-1-thread-4] org.example.singleton.SingletonTest      : 线程 pool-1-thread-4 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.714  INFO 8428 --- [pool-1-thread-1] org.example.singleton.SingletonTest      : 线程 pool-1-thread-1 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.714  INFO 8428 --- [pool-1-thread-5] org.example.singleton.SingletonTest      : 线程 pool-1-thread-5 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.714  INFO 8428 --- [pool-1-thread-3] org.example.singleton.SingletonTest      : 线程 pool-1-thread-3 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.716  INFO 8428 --- [pool-1-thread-2] org.example.singleton.SingletonTest      : 线程 pool-1-thread-2 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.716  INFO 8428 --- [ool-1-thread-10] org.example.singleton.SingletonTest      : 线程 pool-1-thread-10 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.716  INFO 8428 --- [pool-1-thread-9] org.example.singleton.SingletonTest      : 线程 pool-1-thread-9 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.717  INFO 8428 --- [pool-1-thread-8] org.example.singleton.SingletonTest      : 线程 pool-1-thread-8 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.716  INFO 8428 --- [pool-1-thread-7] org.example.singleton.SingletonTest      : 线程 pool-1-thread-7 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc
2021-03-04 13:24:16.714  INFO 8428 --- [pool-1-thread-6] org.example.singleton.SingletonTest      : 线程 pool-1-thread-6 获取到的实例: org.example.singleton.HungrySingleton@1479e6cc

获取的10个实例对象内存地址相同。

懒汉式

也叫延迟加载方式,当系统需要使用时,创建实例。这种方式在类加载时,只是声明了一个空间,但并为创建实例对象,当进程内首次获取对象时,会先创建一个实例,然后返回,后续则返回第一次创建的实例。但是这种模式是线程不安全的,当出现并发时,可能会创建多个实例对象,所以需要引入锁机制来保证线程安全,本文的处理方式是 加入常用的双重检验锁。

public class LazySingleton {

    private LazySingleton(){}

    private static LazySingleton lazySingleton;

    public static LazySingleton getInstance (){
        if (lazySingleton == null){
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}

测试代码

	@Test
    public void testLazyWithNoDoubleLockSingleton() throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(10);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.submit(() ->{
                try {
                    //等待
                    cdl.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                LazySingleton instance = LazySingleton.getInstance();
                log.info("线程 {} 获取到的实例: {}",Thread.currentThread().getName(),instance);
            });
            //计数器-1
            cdl.countDown();
        }

        executorService.awaitTermination(5, TimeUnit.SECONDS);
        executorService.shutdown();
    }

说明:

2021-03-04 13:41:00.361  INFO 14632 --- [pool-1-thread-2] org.example.singleton.SingletonTest      : 线程 pool-1-thread-2 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.362  INFO 14632 --- [ool-1-thread-10] org.example.singleton.SingletonTest      : 线程 pool-1-thread-10 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.363  INFO 14632 --- [pool-1-thread-1] org.example.singleton.SingletonTest      : 线程 pool-1-thread-1 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.363  INFO 14632 --- [pool-1-thread-8] org.example.singleton.SingletonTest      : 线程 pool-1-thread-8 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.362  INFO 14632 --- [pool-1-thread-7] org.example.singleton.SingletonTest      : 线程 pool-1-thread-7 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.362  INFO 14632 --- [pool-1-thread-3] org.example.singleton.SingletonTest      : 线程 pool-1-thread-3 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.362  INFO 14632 --- [pool-1-thread-4] org.example.singleton.SingletonTest      : 线程 pool-1-thread-4 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.362  INFO 14632 --- [pool-1-thread-9] org.example.singleton.SingletonTest      : 线程 pool-1-thread-9 获取到的实例: org.example.singleton.LazySingleton@447e4749
2021-03-04 13:41:00.362  INFO 14632 --- [pool-1-thread-5] org.example.singleton.SingletonTest      : 线程 pool-1-thread-5 获取到的实例: org.example.singleton.LazySingleton@1bf38d27
2021-03-04 13:41:00.362  INFO 14632 --- [pool-1-thread-6] org.example.singleton.SingletonTest      : 线程 pool-1-thread-6 获取到的实例: org.example.singleton.LazySingleton@447e4749

由日志信息可知:pool-1-thread-5获取到的实例的地址与其他线程不相同,说明此种单例模式,线程不安全。

为了提升线程安全性,需要对代码进行改造,代码中引入了双重检验锁

public class LazyWithDoubleLockSingleton {

    private LazyWithDoubleLockSingleton(){}

    private static LazyWithDoubleLockSingleton lazySingleton;

    public static LazyWithDoubleLockSingleton getInstance (){
        if (lazySingleton == null){
            synchronized (LazyWithDoubleLockSingleton.class){
                if (lazySingleton == null){
                    lazySingleton = new LazyWithDoubleLockSingleton();
                }
            }
        }
        return lazySingleton;
    }
}

测试代码

    @Test
    public void testLazyWithDoubleLockSingleton() throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(20);
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        for (int i = 0; i < 20; i++) {
            executorService.submit(() ->{
                try {
                    cdl.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                LazyWithDoubleLockSingleton instance = LazyWithDoubleLockSingleton.getInstance();
                log.info("线程 {} 获取到的实例: {}",Thread.currentThread().getName(),instance);
            });
            cdl.countDown();
        }

        executorService.awaitTermination(5, TimeUnit.SECONDS);
        executorService.shutdown();
    }

说明:开启20个线程,获取实例日志信息:

2021-03-04 14:14:45.560  INFO 11008 --- [ool-1-thread-11] org.example.singleton.SingletonTest      : 线程 pool-1-thread-11 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.561  INFO 11008 --- [ool-1-thread-20] org.example.singleton.SingletonTest      : 线程 pool-1-thread-20 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.560  INFO 11008 --- [ool-1-thread-15] org.example.singleton.SingletonTest      : 线程 pool-1-thread-15 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.560  INFO 11008 --- [pool-1-thread-2] org.example.singleton.SingletonTest      : 线程 pool-1-thread-2 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.560  INFO 11008 --- [pool-1-thread-4] org.example.singleton.SingletonTest      : 线程 pool-1-thread-4 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.562  INFO 11008 --- [pool-1-thread-8] org.example.singleton.SingletonTest      : 线程 pool-1-thread-8 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.559  INFO 11008 --- [pool-1-thread-5] org.example.singleton.SingletonTest      : 线程 pool-1-thread-5 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.559  INFO 11008 --- [pool-1-thread-6] org.example.singleton.SingletonTest      : 线程 pool-1-thread-6 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.559  INFO 11008 --- [pool-1-thread-3] org.example.singleton.SingletonTest      : 线程 pool-1-thread-3 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.559  INFO 11008 --- [ool-1-thread-18] org.example.singleton.SingletonTest      : 线程 pool-1-thread-18 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.559  INFO 11008 --- [ool-1-thread-19] org.example.singleton.SingletonTest      : 线程 pool-1-thread-19 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.559  INFO 11008 --- [pool-1-thread-7] org.example.singleton.SingletonTest      : 线程 pool-1-thread-7 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.564  INFO 11008 --- [ool-1-thread-17] org.example.singleton.SingletonTest      : 线程 pool-1-thread-17 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.558  INFO 11008 --- [ool-1-thread-12] org.example.singleton.SingletonTest      : 线程 pool-1-thread-12 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.564  INFO 11008 --- [pool-1-thread-1] org.example.singleton.SingletonTest      : 线程 pool-1-thread-1 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.564  INFO 11008 --- [ool-1-thread-10] org.example.singleton.SingletonTest      : 线程 pool-1-thread-10 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.564  INFO 11008 --- [ool-1-thread-14] org.example.singleton.SingletonTest      : 线程 pool-1-thread-14 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.560  INFO 11008 --- [pool-1-thread-9] org.example.singleton.SingletonTest      : 线程 pool-1-thread-9 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.560  INFO 11008 --- [ool-1-thread-16] org.example.singleton.SingletonTest      : 线程 pool-1-thread-16 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446
2021-03-04 14:14:45.560  INFO 11008 --- [ool-1-thread-13] org.example.singleton.SingletonTest      : 线程 pool-1-thread-13 获取到的实例: org.example.singleton.LazyWithDoubleLockSingleton@2bde9446

由以上日志信息可知,加了双重检验锁后,20个线程获取的实例均相同。

枚举式

枚举式单例,线程安全

  1. 定义一个类Person
public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }
}
  1. 定义枚举
@Getter
public enum  EnumSingleton {

    PERSON(new Person("befory"));

    private Person person;

    EnumSingleton(Person person) {
        this.person = person;
    }
}

测试代码

    @Test
    public void testEnumSingleton() throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(10);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.submit(() ->{
                try {
                    cdl.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person instance = EnumSingleton.PERSON.getPerson();
                log.info("线程 {} 获取到的实例: {}",Thread.currentThread().getName(),instance);
            });
            cdl.countDown();
        }

        executorService.awaitTermination(5, TimeUnit.SECONDS);
        executorService.shutdown();
    }

运行日志信息:

2021-03-04 14:17:10.939  INFO 11688 --- [pool-1-thread-3] org.example.singleton.SingletonTest      : 线程 pool-1-thread-3 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.938  INFO 11688 --- [pool-1-thread-1] org.example.singleton.SingletonTest      : 线程 pool-1-thread-1 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.939  INFO 11688 --- [pool-1-thread-8] org.example.singleton.SingletonTest      : 线程 pool-1-thread-8 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.939  INFO 11688 --- [pool-1-thread-5] org.example.singleton.SingletonTest      : 线程 pool-1-thread-5 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.940  INFO 11688 --- [pool-1-thread-6] org.example.singleton.SingletonTest      : 线程 pool-1-thread-6 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.939  INFO 11688 --- [pool-1-thread-9] org.example.singleton.SingletonTest      : 线程 pool-1-thread-9 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.939  INFO 11688 --- [pool-1-thread-7] org.example.singleton.SingletonTest      : 线程 pool-1-thread-7 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.938  INFO 11688 --- [ool-1-thread-10] org.example.singleton.SingletonTest      : 线程 pool-1-thread-10 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.938  INFO 11688 --- [pool-1-thread-4] org.example.singleton.SingletonTest      : 线程 pool-1-thread-4 获取到的实例: org.example.singleton.Person@34f864c5
2021-03-04 14:17:10.938  INFO 11688 --- [pool-1-thread-2] org.example.singleton.SingletonTest      : 线程 pool-1-thread-2 获取到的实例: org.example.singleton.Person@34f864c5

结论:地址相同

内部类

也叫登记式,类部拥有一个静态内部类,静态内部类中拥有一个实例化的对象,一个类中可以拥有多个静态内部类,它可以实现多种策略的单例模式,由于静态内部类加载机制,这种方式属于延迟加载(在使用时加载),但同时它又保证了线程安全。

public class InnerSingleton {

    private InnerSingleton(){}

    public static class Holder{
        public static  InnerSingleton INSTANCE = new InnerSingleton();
    }
}

测试代码

    @Test
    public void testInnerSingleton() throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(10);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.submit(() ->{
                try {
                    cdl.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                InnerSingleton instance = InnerSingleton.Holder.INSTANCE;
                log.info("线程 {} 获取到的实例: {}",Thread.currentThread().getName(),instance);
            });
            cdl.countDown();
        }

        executorService.awaitTermination(5, TimeUnit.SECONDS);
        executorService.shutdown();
    }

运行日志

2021-03-04 14:24:59.135  INFO 14160 --- [pool-1-thread-8] org.example.singleton.SingletonTest      : 线程 pool-1-thread-8 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.134  INFO 14160 --- [pool-1-thread-1] org.example.singleton.SingletonTest      : 线程 pool-1-thread-1 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.135  INFO 14160 --- [pool-1-thread-3] org.example.singleton.SingletonTest      : 线程 pool-1-thread-3 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.135  INFO 14160 --- [pool-1-thread-2] org.example.singleton.SingletonTest      : 线程 pool-1-thread-2 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.136  INFO 14160 --- [pool-1-thread-9] org.example.singleton.SingletonTest      : 线程 pool-1-thread-9 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.135  INFO 14160 --- [pool-1-thread-5] org.example.singleton.SingletonTest      : 线程 pool-1-thread-5 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.135  INFO 14160 --- [pool-1-thread-6] org.example.singleton.SingletonTest      : 线程 pool-1-thread-6 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.135  INFO 14160 --- [pool-1-thread-7] org.example.singleton.SingletonTest      : 线程 pool-1-thread-7 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.135  INFO 14160 --- [pool-1-thread-4] org.example.singleton.SingletonTest      : 线程 pool-1-thread-4 获取到的实例: org.example.singleton.InnerSingleton@5c1be49
2021-03-04 14:24:59.135  INFO 14160 --- [ool-1-thread-10] org.example.singleton.SingletonTest      : 线程 pool-1-thread-10 获取到的实例: org.example.singleton.InnerSingleton@5c1be49

日志信息显示 内存地址相同

容器式

容器式单例与其他几种类型单例不同,容器式单例需要先创建一个容器的实例,容器是单例。这种方式也是springIOC容器实现的一种方式

public class ContainerSingleton {

    // 定义容器
    private static final ConcurrentHashMap<String,Person> CONTAINER =  new ConcurrentHashMap<>();

    public static Person getInstance(String name){
        if (CONTAINER.containsKey(name)){
            return CONTAINER.get(name);
        }
        Person person = new Person("befory");
        CONTAINER.put(name,person);
        return person;
    }
}

测试代码

    @Test
    public void testContainerSingleton() throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(10);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.submit(() ->{
                try {
                    cdl.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person instance = ContainerSingleton.getInstance("befory");
                log.info("线程 {} 获取到的实例: {}",Thread.currentThread().getName(),instance);
            });
            cdl.countDown();
        }

        executorService.awaitTermination(5, TimeUnit.SECONDS);
        executorService.shutdown();
    }

日志信息

2021-03-04 17:05:39.718  INFO 15456 --- [pool-1-thread-7] org.example.singleton.SingletonTest      : 线程 pool-1-thread-7 获取到的实例: org.example.singleton.Person@4d914f9d
2021-03-04 17:05:39.717  INFO 15456 --- [pool-1-thread-4] org.example.singleton.SingletonTest      : 线程 pool-1-thread-4 获取到的实例: org.example.singleton.Person@4df33374
2021-03-04 17:05:39.718  INFO 15456 --- [pool-1-thread-3] org.example.singleton.SingletonTest      : 线程 pool-1-thread-3 获取到的实例: org.example.singleton.Person@22230c
2021-03-04 17:05:39.718  INFO 15456 --- [pool-1-thread-8] org.example.singleton.SingletonTest      : 线程 pool-1-thread-8 获取到的实例: org.example.singleton.Person@56e930d4
2021-03-04 17:05:39.717  INFO 15456 --- [ool-1-thread-10] org.example.singleton.SingletonTest      : 线程 pool-1-thread-10 获取到的实例: org.example.singleton.Person@539d2805
2021-03-04 17:05:39.717  INFO 15456 --- [pool-1-thread-2] org.example.singleton.SingletonTest      : 线程 pool-1-thread-2 获取到的实例: org.example.singleton.Person@5b1cf141
2021-03-04 17:05:39.719  INFO 15456 --- [pool-1-thread-9] org.example.singleton.SingletonTest      : 线程 pool-1-thread-9 获取到的实例: org.example.singleton.Person@1244b7e5
2021-03-04 17:05:39.720  INFO 15456 --- [pool-1-thread-6] org.example.singleton.SingletonTest      : 线程 pool-1-thread-6 获取到的实例: org.example.singleton.Person@1244b7e5
2021-03-04 17:05:39.717  INFO 15456 --- [pool-1-thread-5] org.example.singleton.SingletonTest      : 线程 pool-1-thread-5 获取到的实例: org.example.singleton.Person@72896df6
2021-03-04 17:05:39.720  INFO 15456 --- [pool-1-thread-1] org.example.singleton.SingletonTest      : 线程 pool-1-thread-1 获取到的实例: org.example.singleton.Person@1244b7e5

由上面日志信息可知,发现创建了多个Person实例对象。所以需要对其进行改造,改造代码如下:

public class ContainerSingleton {

    // 定义容器
    private static final ConcurrentHashMap<String,Person> CONTAINER =  new ConcurrentHashMap<>();

    public static Person getInstance(String name){
        if (!CONTAINER.containsKey(name)){
            synchronized (ContainerSingleton.class){
                if (!CONTAINER.containsKey(name)){
                    Person person = new Person("befory");
                    CONTAINER.put(name,person);
                }
            }
        }
        return CONTAINER.get(name);
    }
}

类似懒汉式单例中加强线程安全做法,加了检验机制,获取到的日志信息如下:

2021-03-04 17:12:36.987  INFO 15480 --- [pool-1-thread-8] org.example.singleton.SingletonTest      : 线程 pool-1-thread-8 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.987  INFO 15480 --- [pool-1-thread-1] org.example.singleton.SingletonTest      : 线程 pool-1-thread-1 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.989  INFO 15480 --- [pool-1-thread-5] org.example.singleton.SingletonTest      : 线程 pool-1-thread-5 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.987  INFO 15480 --- [pool-1-thread-9] org.example.singleton.SingletonTest      : 线程 pool-1-thread-9 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.990  INFO 15480 --- [pool-1-thread-6] org.example.singleton.SingletonTest      : 线程 pool-1-thread-6 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.990  INFO 15480 --- [ool-1-thread-10] org.example.singleton.SingletonTest      : 线程 pool-1-thread-10 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.988  INFO 15480 --- [pool-1-thread-3] org.example.singleton.SingletonTest      : 线程 pool-1-thread-3 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.990  INFO 15480 --- [pool-1-thread-4] org.example.singleton.SingletonTest      : 线程 pool-1-thread-4 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.991  INFO 15480 --- [pool-1-thread-2] org.example.singleton.SingletonTest      : 线程 pool-1-thread-2 获取到的实例: org.example.singleton.Person@25fa0461
2021-03-04 17:12:36.987  INFO 15480 --- [pool-1-thread-7] org.example.singleton.SingletonTest      : 线程 pool-1-thread-7 获取到的实例: org.example.singleton.Person@25fa0461

经过多次运行查看,从日志信息显示,获取实例地址均相同。

结论

各种方式的单例,都有各自的缺点,本文只是对线程安全上进行了对比与验证,得出的诸多结论。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值