单例模式是Java中最简单的设计模式之一,在Java语言中单例模式的定义:“一个类有且只有一个实例,并且自行实例化后向整个系统提供”。
在Java中实现单例模式需要注意以下三点:
- 是单例模式的类只提供私有的构造函数。
- 是类定义中含有一个该类的静态私有对象,。
- 是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
我们先来简单的实现一个单例模式。
public class SingletonDemo {
private SingletonDemo() {
}
private static volatile SingletonDemo instance = null;
public static SingletonDemo getInstance() {
if(null == instance) {
synchronized (SingletonDemo.class) {
if(null == instance) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}
上面是一个使用双检锁的方式实现的一个单例模式,使用synchronized 和volatile关键字确保第一次创建时没有因为线程间的互相竞争而产生多个实例。该方式在多线程的情况下能确保安全且性能相对较高。除了双检锁,还有其它多种方式来实现单例,下面就让我们简单了解一下。
懒汉式是实现单例模式的最简单的方式,在多线程的情况下懒汉式根据方法是否添加synchronized 关键字判断是否线程安全。在多数的开发过程中大都使用这种方式实现单例。
public class SingletonDemo {
private SingletonDemo() {
}
private static SingletonDemo instance = null;
public static synchronized SingletonDemo getInstance() {
if(null == instance) {
instance = new SingletonDemo();
}
return instance;
}
}
饿汉式是实现单例的第三种模式,这种模式下类加载时就创建了实例对象。这种代码在我们工作中能经常看到。
public class SingletonDemo {
private SingletonDemo() {
}
private static volatile SingletonDemo instance = new SingletonDemo();
public static SingletonDemo getInstance() {
return instance;
}
}
实现单例的方式还有登记式,这种方式使用静态内部类实例化对象,和饿汉式一样利用classloader的机制保证初始化时只有一个线程。
public class SingletonDemo {
private SingletonDemo() {
}
private static class SingletonDemoHolder {
private static final SingletonDemo INSTANCE = new SingletonDemo();
}
public static final SingletonDemo getInstance() {
return SingletonDemoHolder.INSTANCE;
}
}
除此之外Java中的枚举也是实现单例的一种很好的方法,但是这种方式在开发过程中使用的比较少,多数情况下我们会把这些枚举数据保存到数据库中,这样可以动态配置。