在实际生产的项目中我们一般很少自己使用单例模式,但是在有过间接的使用过他,例如spring的bean单例。 定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。构造器私有化,不能被new出来。
项目代码:Github
几种单例实现:
public class SingleDemo {
private static SingleDemo instance = new SingleDemo();
//私有化构造器
private SingleDemo() {
//防止其他通过反射调用构造方法,破解单例
if (instance != null) {
throw new RuntimeException();
}
}
//对外提供统一的访问点
public static SingleDemo getInstance() {
return instance;
}
}
优点:
缺点:
public class SingleDemo2 {
// 此处并不初始化实例
private static SingleDemo2 instance;
private SingleDemo2() {
if (instance != null) {
throw new RuntimeException();
}
}
/**
* 当调用此方法的时候才初始化实例, 为了实现线程安全,需要使用同步方法
*/
public static synchronized SingleDemo2 getInstance() {
if (instance == null) {
instance = new SingleDemo2();
}
return instance;
}
}
优点:
缺点:
public class SingleDemo3 {
private static SingleDemo3 instance;
private SingleDemo3() {
if (instance != null) {
throw new RuntimeException();
}
}
public static SingleDemo3 getInstance() {
//第一重检查,提高效率
if (instance == null) {
synchronized (SingleDemo3.class) {
//第二重检查保证线程安全
if (instance == null) {
instance = new SingleDemo3();
}
}
}
return instance;
}
}
优点:
缺点:
public class SingleDemo4 {
private static SingleDemo4 instance;
private static class SingleDemo4Holder {
private static final SingleDemo4 instance = new SingleDemo4();
}
private SingleDemo4() {
if (instance != null) {
throw new RuntimeException();
}
}
/**
* 调用这个方法的时候,JVM才加载静态内部类,才初始化静态内部类的类变量。由于由JVM初始化,保证了线程安全性,
* 同时又实现了懒加载
*/
public static SingleDemo4 getInstance() {
return SingleDemo4Holder.instance;
}
}
优点:
缺点:
public enum SingleDemo5 {
INSTANCE;
public void someMethod(){
}
}
优点:
缺点:
如果需要懒加载就使用静态内部类方式,如果不需要就使用枚举方式
如果要求一个类只能生产固定数量的实例。
public class SingleDemo6{
// 最多可以生成的单例数量
private static int maxNumberSingleDemo = 2;
// 定义列表存放实例
private static List<SingleDemo6> singleDemoList = new ArrayList<>();
//生成对象
static{
for(int i=0; i<maxNumberSingleDemo; i++){
singleDemoList.add(new SingleDemo6());
}
}
private SingleDemo6(){}
public static SingleDemo6 getInstance(){
Random random = new Random();
//随机调用一个实例
int number = random.nextInt(maxNumberSingleDemo);
return singleDemoList.get(number);
}
}
这种需要产生固定数量对象的模式就叫做有上限的多例模式, 它是单例模式的一种扩展, 采用有上限的多例模式, 我们可以在设计时决定在内存中有多少个实例, 方便系统进行 扩展, 修正单例可能存在的性能问题, 提供系统的响应速度。 例如读取文件, 我们可以在系 统启动时完成初始化工作, 在内存中启动固定数量的reader实例, 然后在需要读取文件时就 可以快速响应。