Java——面试官让你手写单例模式,你能写出几种?

Posted 张起灵-小哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java——面试官让你手写单例模式,你能写出几种?相关的知识,希望对你有一定的参考价值。

写在前面

单例模式应该来说,是23种设计模式中最简单的一种了,它说的也就是一个实例呗,当我们获得对象的时候,每次获得的都是同一个,那么我们可以先创建好一个实例对象,然后写一个public公共的get方法,每次创建的时候,通过get方法获取该实例,那么就达到了单例效果,需要注意的是,我们要将构造方法定义为private私有的,目的是以免外面new这个单例对象。 

单例模式了话,我听到见到的大概有5、6、7、8种???唉,可能是我太水了,有些真的写不出来。下面我就给出常见的5种吧!!!

第一种:饿汉式

/**
 * 单例模式:饿汉式
 * 在获取对象之前已经将其创建好了,感觉“很饿”
 * 这样其实不好,因为我都没有用到这个对象,你都创建了,多浪费呀
 */
public class Singleton {

    public static Singleton instance=new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {
        return instance;
    }
}

第二种:懒汉式

/**
 * 单例模式:懒汉式
 * 这种方式是等用到了才去创建,给人的感觉是很懒,所以又叫“懒汉式”
 * 仔细看看这种写法,其实存在线程安全问题,当有多线程调用getInstance方法的时候
 * 第一个线程判断instance为null,进入了 if,当还没来得及创建对象的时候,
 * 第二个线程也判断instance为null,也进入了 if,于是就会创建多个对象,无法达到单例效果
 */
public class Singleton {

    public static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance=new Singleton();
        }
        return instance;
    }
}

第三种:懒汉式 + 线程同步synchronized (锁到方法上)

/**
 * 单例模式:懒汉式 + 线程同步synchronized (锁到方法上)
 * 所以我们可以引入锁来解决懒汉式的问题,
 * 当第一个线程进来判断instance为null,进入了 if,即使还没来得及创建对象,但是这里已经上锁了,
 * 第二个进程根本就进不来这个get方法,必须等待第一个线程执行完这个get方法才行
 * 这样有效的解决了线程安全的问题,但是,这个锁,锁到了方法上,范围有点大了
 * 其实我们只需要锁出现线程安全的一部分就行了
 */
public class Singleton {

    public static Singleton instance;

    private Singleton() {

    }

    public synchronized static Singleton getInstance() {
        if (instance == null) {
            instance=new Singleton();
        }
        return instance;
    }
}

第四种:懒汉式 + 线程同步synchronized (锁到某个代码块中)

/**
 * 单例模式:懒汉式 + 线程同步synchronized (锁到某个代码块中)
 * 该方法在之前的基础上做了一点改进,只锁了new对象的那一部分
 * 当线程来了的时候,先判断instance是否为空,为空就上锁,不空直接return
 * 但是问题来了,当出现多线程时,第一个线程判断instance为null,进入锁,还没来得及创建对象
 * 第二个线程来了判断instance也为null,它会在这个if下面等待
 * 当第一个线程走了之后,第二个线程也进入了锁,执行了new,这样线程也不安全了,
 */
public class Singleton {

    public static Singleton instance;

    private Singleton() {

    }

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

第五种:双重校验锁DCL

package com.szh.singleton05;

/**
 * 单例模式:双重校验锁DCL
 * 前面那四种方式,一步步的演变出了最终的版本
 * 这里当第一个线程进入了第一个if,判断instance是否为空(此时第二个线程来了,在第一个if这里等待),为空就上锁,
 * 第一个线程进入第二个if,判断instance是否为空,进而创建对象
 * 当第一个线程走了之后,第二个线程进入上锁,但是此时遇到第二个if,再次判断instance是否为空
 * 此时instance已经new过了,不为空,所以第二个线程执行到这里,就不会再new对象了,也就实现了单例
 */
public class Singleton {

    public static volatile Singleton instance;

    private Singleton() {

    }

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

 

以上是关于Java——面试官让你手写单例模式,你能写出几种?的主要内容,如果未能解决你的问题,请参考以下文章

Java面试必备:手写单例模式

面试官让你手写单例模式

如何写出面试官欣赏的Java单例

java真实面试_深圳百纳九州_java的基本数据类型有几种,并且写出全部的数据类型写出常用的Linux命令finalfinalize和finnally的不同之处用java手写一个单例类

JAVA如何正确地写出单例模式(转)

面试官让手写队列,差点没写出来