四种单例写法与测试
Posted muche-moqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四种单例写法与测试相关的知识,希望对你有一定的参考价值。
四种单例写法与测试
本文主要实现了四种方式的单例模式与测试,双重检测代码稍微麻烦点。每一个类都设有一个测试方法,可以替换自己需要做的一些业务。
各种方式需要注意的点:
- 饿汉式
- 私有化构造函数
- final定义instance
- 双重检测
- 私有化构造函数
- volatile修饰instance,否则会可能得到未初始化的实例
- 可替换为其他非静态实例使用
- 静态内部类
- 私有化构造函数
- 只能静态实例
- 枚举
- 不用构造函数
- 可定义多个枚举,如:enum{ IN1, INS2 }则实现多例
- 保证线程安全,唯一不会被反射和序列化影响的单例模式
参考:
你知道吗?枚举单例模式是世界上最好的单例模式
《java 并发编程的艺术》
《effective java》
以下是代码:
import java.util.concurrent.atomic.AtomicLong;
public class Singleton {
public static void main(String[] args) {
//测试饿汉式
HungrySingleton h1 = HungrySingleton.getInstance();
HungrySingleton h2 = HungrySingleton.getInstance();
System.out.println("两个实例是否相等:" + (h1 == h2));
System.out.println("第一次加" + h1.getId());
System.out.println("第二次加" + h2.getId());
System.out.println("------------------------------------");
//测试双重检测
DoubleCheckSingleton d1 = DoubleCheckSingleton.getInstance();
DoubleCheckSingleton d2 = DoubleCheckSingleton.getInstance();
System.out.println("两个实例是否相等:" + (d1 == d2));
System.out.println("第一次加" + d1.getId());
System.out.println("第二次加" + d2.getId());
System.out.println("------------------------------------");
//测试静态内部类
StatiInnerClassSingleton s1 = StatiInnerClassSingleton.getInstance();
StatiInnerClassSingleton s2 = StatiInnerClassSingleton.getInstance();
System.out.println("两个实例是否相等:" + (s1 == s2));
System.out.println("第一次加" + s1.getId());
System.out.println("第二次加" + s2.getId());
System.out.println("------------------------------------");
//测试枚举
EnumSingleton e1 = EnumSingleton.INSTANCE;
EnumSingleton e2 = EnumSingleton.INSTANCE;
System.out.println("两个实例是否相等:" + (e1 == e2));
System.out.println("第一次加" + e1.getId());
System.out.println("第二次加" + e2.getId());
}
}
/**
* 饿汉式
*/
class HungrySingleton{
private static final HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return instance;
}
//用于测试单例正确性
private AtomicLong id = new AtomicLong(0);
public long getId() {
return id.incrementAndGet();
}
}
/**
* 双重检测
*/
class DoubleCheckSingleton{
private static volatile DoubleCheckSingleton instance = null;
private DoubleCheckSingleton(){}
public static DoubleCheckSingleton getInstance(){
if(instance == null){
synchronized (DoubleCheckSingleton.class){
if(instance == null){
instance = new DoubleCheckSingleton();
}
}
}
return instance;
}
//用于测试单例正确性
private AtomicLong id = new AtomicLong(0);
public long getId() {
return id.incrementAndGet();
}
}
/**
* 静态内部类
*/
class StatiInnerClassSingleton{
private StatiInnerClassSingleton(){}
private static class InstanceHolder{
public static StatiInnerClassSingleton instance = new StatiInnerClassSingleton();
}
public static StatiInnerClassSingleton getInstance(){
return InstanceHolder.instance;
}
//用于测试单例正确性
private AtomicLong id = new AtomicLong(0);
public long getId() {
return id.incrementAndGet();
}
}
/**
* 枚举
*/
enum EnumSingleton{
INSTANCE;
//用于测试单例正确性
private AtomicLong id = new AtomicLong(0);
public long getId() {
return id.incrementAndGet();
}
}
以上是关于四种单例写法与测试的主要内容,如果未能解决你的问题,请参考以下文章