今天要为大家分享的是Java如何实现单例模式。
1、前言
经常同事在一起聊单例模式,所在项目中也是各种方式实现的单例模式,有的还是漏洞百出,各种面试也会问到,可是真的细究发现自己并没有一个完善的认识,今天就单例模式整理下。
2、什么是单例模式
单例对象的类必须保证只有一个实例存在——这是维基百科上对单例的定义,这也可以作为对意图实现单例模式的代码进行检验的标准。
对单例的实现可以分为两大类——懒汉式和饿汉式,他们的区别在于:懒汉式:指全局的单例实例在第一次被使用时构建。饿汉式:指全局的单例实例在类装载时构建。
从它们的区别也能看出来,日常我们使用的较多的应该是懒汉式的单例,毕竟按需加载才能做到资源的大化利用嘛~
3、懒汉式单例
经常会问应聘者:“知道设计模式,简单介绍下?”应聘者:“单例模式.....就是JVM中保持只有一个的实例,实现方式就是把构造方法私有,自己实现一个获取方法.....”。嗯,看来大家的单例模式都是懒汉式了。那就先讲讲懒汉式吧,其实不管怎么个实现,还是那句话--为了保证单例对象的类必须只有一个实例存在。那下面就谈谈懒汉式的演变。
3.1Java实现单例模式的简单版本
看简单的写法Version 1:
/**
* 简单版本的单例模式
* Created by zhangyhk on 2017/5/16.
*/
public class Single1 {
private static Single1 instance;
public static Single1 getInstance(){
if(null==instance){
instance = new Single1();
}
return instance;
}}
或者再进一步,把构造器改为私有的,这样能够防止被外部的类调用。
/**
* 简单版本的单例模式
* 构造方法私有
* Created by zhangyhk on 2017/5/16.
*/
public class Single1 {
private static Single1 instance;
private Single1(){};
public static Single1 getInstance(){
if(null==instance){
instance = new Single1();
}
return instance;
}}
每次获取instance之前先进行判断,如果instance为空就new一个出来,否则就直接返回已存在的instance。这种写法在大多数的时候也是没问题的。问题在于,当多线程工作的时候,如果有多个线程同时运行到if (instance == null),都判断为null,那么两个线程就各自会创建一个实例——这样一来,就不是单例了。
3.2 synchronized版本
既然可能因为多线程有问题,那么就加锁吧,java处理多线程问题,就是加锁,在大多数情况下都是“synchronized”关键字,我经常会问StringBuilder和StringBuffer哪个是线程安全的?为什么?大多数会回答StringBuffer可是“为什么?”都回答的不是很好,其实JDK里大部分的线程安全实现方式都是加“synchronized”,当然还有别的实现方式这里就不详细说了。
修改后的代码如下,相对于Version1.1,只是在方法签名上多加了一个synchronized:
/**
* 简单版本的单例模式
* Created by zhangyhk on 2017/5/16.
*/
public class Single2 {
private static Single2 instance;
private Single2(){};
public static synchronized Single2 getInstance(){
if (null==instance){
instance = new Single2();
}
return instance;
}}
热点新闻