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的基本数据类型有几种,并且写出全部的数据类型写出常用的Linux命令finalfinalize和finnally的不同之处用java手写一个单例类