0 单例模式简介
单例模式属于创建型模式,它提供了一种创建对象的最佳方式。单例模式指的是单一的一个类,该类负责创建自己的对象,并且保证该对象唯一。该类提供了一种访问其唯一对象的方法,外部需要调用该类的对象可以通过方法获取,不需要实例化类的对象。
关键点:
- 单例类只能有一个实例
- 单例类只能自己创建自己的唯一实例
- 单例类需要给其他对象提供这一实例
1 实现方式
创建一个Singleton单例类,单例类有一个私有的构造方法和私有的唯一静态实例。Singleton对象提供了一个公有的静态方法,供外界调用其唯一的静态实例。SingletonDemo类使用Singleton类来获取Singleton对象。
此处主要用以下三种创建方式举例说明。
1.1 懒汉式,线程安全
- 优点:第一次调用才初始化,避免内存资源浪费
- 缺点:必须要加synchronize锁才能保证单例,但是加锁会影响效率
创建单例类:
public class Singleton {
//实现方式一:懒汉式 线程不安全
private static Singleton instance;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(instance == null) {
instance = new Singleton();
}
return instance;
}
public void show() {
System.out.println("singleton");
}
}
调用单例类获取唯一对象实例:
public class SingletonDemo {
public static void main(String[] args) {
//获取唯一的可用对象
Singleton obj = Singleton.getInstance();
//调用instance的方法
obj.show();
}
}
1.2 饿汉式,线程安全
- 优点:没有加锁,执行效率更高
- 缺点:类加载时就会实例化,浪费内存
该方式基于 classloader 机制避免了多线程的同步问题。
创建单例类:
public class Singleton {
//实现方式二:饿汉式 线程安全
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
public void show() {
System.out.println("singleton");
}
}
1.3 双检锁/双重校验锁
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
public class Singleton {
//实现方式三:双重校验锁 线程安全
private volatile static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if (instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
public void show() {
System.out.println("singleton");
}
}
2 小结
- 单例类仅有一个实例,并且对外提供获取实例的方法
- 主要解决一个全局使用的类频繁的创建与销毁
- 构造方法为私有