单例模式是一中很重要的设计模式,各种框架运用都非常的多。我个人觉得,单例模式可以非常简单,也可以比较复杂,看你怎么实现。单例模式常见的写法分为两种写法,分别是饿汉式和懒汉式,这我相信大家都是比较了解的,这两天学习的时候,听到了第三种写法,使用静态内部类来实现。下面我们就来通过代码来分别实现一下
1. 单例模式之饿汉式
其实我个人觉得饿汉式是单例模式中性价比最高的一种写法了,我有主要是从这几方面来考虑的。首先单例模式的饿汉式写法简单,别人很容易理解,其次饿汉式写法还可以在不加锁的情况下避免多线程环境下的并发问题,当然也不是没有缺点,可能最让人可以想到的缺点就是占用内存资源了。饿汉式写法如下
public class Singleton {
private Singleton() {}
private final static Singleton SINGLETON = new Singleton();
public static Singleton getInstance() {
return SINGLETON;
}
}
这种写法其实还是很好理解的,就不再过多的说明了,接下来介绍懒汉式写法
2. 单例模式之懒汉式
单例模式的懒汉式写法最多,网上也特别多这方面的技术博客,我也看了挺多的,各种的演化版本,一个版本比一个版本完善,我这里就提供两个版本吧,一个是原始版本,一个是最完美的版本,原始版本对应的源码如下
public class SingletonA {
private SingletonA() {}
private static SingletonA SINGLETON;
public static SingletonA getInstance() {
if (SINGLETON == null) {
SINGLETON = new SingletonA();
}
return SINGLETON;
}
}
号称最完美的懒汉式写法如下
public class SingletonA {
private SingletonA() {}
//volatile关键字可以保证线程之间的可见性,当某个线程创建对象后,变量SINGLETON变化后,其他线程可以知道变化
private static volatile SingletonA SINGLETON;
public static SingletonA getInstance() {
if (SINGLETON == null) {
synchronized (SingletonA.class) {
if (SINGLETON == null)
SINGLETON = new SingletonA();
}
}
return SINGLETON;
}
}
以上两种是比较常见的两种单例模式的写法,另外第三中写法是通过内部类来实现,这种实现也是一种不需要加锁的实现方式,效率上比饿汉式更加高效
3. 单例模式之内部类
内部类的实现是通过Java的类加载特点来实现的一个特殊写法,实现方式如下
public class SingletonB {
private SingletonB() {}
private static class Holder {
private static final SingletonB SINGLETON = new SingletonB();
}
public static SingletonB getInstance() {
return Holder.SINGLETON;
}
}
这个就需要我们验证一下类和内部类的加载方式了,我们通过一个代码来验证
public class TestStaticClass {
static {
System.out.println("加载外部类。。。");
}
public static class InnerClass {
static {
System.out.println("加载内部类。。。");
}
public static void testMethod() {
System.out.println("执行内部类方法。。。");
}
}
}
测试结果如下
可以得出结论:加载一个类时,其内部类不会同时被加载。一个类被加载的时机在其某个静态成员(静态域、构造器、静态方法等)被调用时才会被加载。
所以根据这个特性,当单例类被加载时,单例类的内部类是不会加载的,只有当单例类的静态成员(静态域,构造器,静态方法)被调用时才会被加载。所以源码中SingletonB加载时,其内部类Holder并不会被加载,只有当调用了getInstance方法时,方法中调用了Holder的静态成员变量SINGLETON后,Holder被加载并执行创建对象的操作,而类加载只会加载一次,所以这种也可以实现单例,并且在未加锁的情况下。
以上是我对单例模式各个版本写法的一些理解总结,欢迎讨论。。。