1. 什么是单例模式
就是采取一定的方法保证在整个软件系统中,对某个类只存在一个实例对象,并且该类只提供一个取得其对象实例的方法。
1.1 作用
保证在整个应用程序的声明周期中,任何一个时刻,单例类的实例都只存在一个(也可以不存在)。
1.2 设计要求
单例类的构造函数必须为私有,同时单例类必须提供一个全局访问点。
1.3 单例模式UML图
1.4 使用场景
需要频繁进行创建和销毁的对象;重量级对象。
2. 单例模式的实现
2.1 饿汉式(静态变量)
public class Singleton {
private static final Singleton instance
= new Singleton();
private Singleton(){
}
public static Singleton
getInstance(){
return instance
;
}
}
优缺点说明: 1)写法简单;在类装载的时候就完成实例化,避免了线程同步问题。 2)在类装载的时候就实例化,没有达到懒加载的效果;如果没有使用这个类,会造成内存浪费。
2.2 饿汉式(静态代码块)
public class Singleton {
private static Singleton instance
;
static{
instance
= new Singleton();
}
private Singleton(){
}
public static Singleton
getInstance(){
return instance
;
}
}
优缺点说明: 缺点和优点与静态变量的饿汉式一样。可用,但是若创建出来的类没有使用时,会造成内存浪费。
2.3 懒汉式,不安全
提供一个静态的公有方法,当需要获取对象实例时,采取创建该对象。
public class Singleton {
private static Singleton instance
;
private Singleton(){
}
public static Singleton
getInstance(){
if(instance
== null
){
instance
= new Singleton();
}
return instance
;
}
}
优缺点说明: 1)起到了懒加载效果,在单线程下可用; 2)如果在多线程下,一个线程进入了if(instance==null)判断语句块,在还没来得及往下执行的时候,另一个线程也通过了这个语句块,就会创建多个实例对象。 3)在实际开发中,建议不要使用。
2.4 懒汉式(线程安全,同步方法)
public class Singleton {
private static Singleton instance
;
private Singleton(){
}
public static synchronized Singleton
getInstance(){
if(instance
== null
){
instance
= new Singleton();
}
return instance
;
}
}
优缺点说明: 1)线程安全; 2)效率低。每个线程在想获取对象实例的时候,执行getInstance()方法都需要进行同步,而其实这个方法只执行一次实例化代码就够了,后面想要获得实例对象,只需要return即可。 3)可用,但不推荐。
2.5 双重检查
public class Singleton {
private static Singleton instance
;
private Singleton(){
}
public static synchronized Singleton
getInstance(){
if(instance
==null
){
synchronized(Singleton
.class){
if(instance
==null
){
instance
= new Singleton();
}
}
}
return instance
;
}
}
优缺点说明: 1)线程安全,延迟加载,效率高。实例化代码只执行一次,后面再访问时,判断if(instance==null),直接return,而不进入if语句块,避免了反复创建实例化对象。 2)再实际开发中,推荐使用。
2.6 静态内部类的方式
public class Singleton {
private Singleton(){
}
public static Singleton
getInstance(){
return Inner
.instance
;
}
private static class Inner{
private static final Singleton instance
= new Singleton();
}
}
优缺点说明: 1)采用类加载机制来保证初始化时只有一个线程; 2)静态内部类方式在Singleton类被装载时不会立即被实例化,而是在执行了getInstance()方法后,才会创建实例对象; 3)类的静态属性定义为static final,它只会在第一个加载类时初始化而不能被修改,从而保证了线程的安全性; 4)避免了线程不安全,效率高,实现了延迟加载; 5)推荐使用。
2.7 枚举方式
public class Singleton {
public static void main(String
[] args
){
Method instance01
= Method
.INSTANCE
;
Method instance02
= Method
.INSTANCE
;
System
.out
.println(instance01
==instance02
);
instance01
.work();
}
}
enum Method
{
INSTANCE
;
public void work(){
System
.out
.println("run");
}
}
优缺点说明: 1)不仅能避免多线程同步问题,还能防止反序列化创建新对象; 2)推荐使用。