概念
单例模式其实就是该类只能有一个实例,提供了一种最佳的对象创建方法
目的
单例模式的使用可以确保一个类仅有一个实例,当你想控制实例数目并节省系统资源的时候,使用单例模式可以防止该类频繁的创建与销毁。
代码实现
步骤一:创建一个类A
// 创建一个类A
public class A{
//创建A的一个对象
private static A a = new A();
//使构造函数私有化,防止类被实例化
private A(){}
public static A getA(){
return a;
}
public void show(){
System.out.println("hello");
;
步骤二:从A类中获取唯一的对象
public class SingleA{
public static void main(String[] args){
//报错,构造函数是私有化的
//A single = new A();
//获取唯一对象
A single = A.getA();
//打印消息
single.show();
}
}
;
单例模式的几种实现方式
懒汉式
首先我们来看不加锁的情况
public class A{
private static A a;
private A(){}
public static A getA(){
if(a == null){
a = new A();
}
return a;
}
}
这种方式是最基本的实现,同时也是线程不安全的,不支持多线程,严格来说不算单例模式。
加锁
public class A{
private static A a;
private A(){}
public static synchronized A getA(){
if(a == null){
a = new A();
}
return a;
}
}
此时支持多线程,但效率不好,大多数情况下并不需要同步。
优点:第一次调用才初始化,避免内存浪费
缺点:必须加锁才能保证单例,但加锁又会影响效率。
饿汉式
该方式相较懒汉式比较常用,但容易产生垃圾对象。
public class A{
private static A a = new A();
private A(){}
public static A getA(){
return a;
}
}
优点:没有加锁,执行效率高
缺点:类在加载时就初始化,浪费内存。
双检锁/双重校验锁(DCL,即 double-checked locking)
采用双锁机制,安全并且在多线程下保持高性能。jdk1.5版本开始有的。
public class A{
private volatile static A a;
private A(){}
public static A getA(){
if(a == null){
synchronized(A.class);
if(a == null){
a=new A();
}
}
return a;
}
}
登记式/静态内部类
此方式与双检锁机制拥有一样的功效,但实现更简单
public class A{
private static class AB{
private static final A INSTANCE= new A();
}
private A(){}
public static A getA(){
return AB.INSTANCE;
}
}
枚举
更简洁,自动支持序列化机制,绝对防止多次实例化
public enum A{
INSTANCE;
public void whaterverMethod(){}
}
说明
一般情况下,不推荐使用懒汉式实现单例模式,更多的是使用饿汉式,其他几种实现方式还是需要根据具体情况来使用。