单例模式 是程序开发中用到非常多的一种开发模式,也是面试中一个高频的考点。使用这种模式的主要目的是,确保该类只能创建一个对象。这样做一方面减少对象创建的个数以减少占用内存,另一方面可以减少创建对象的开销。
举个例子来说,一个用来操作某个配置文件(增删改查)的类,没有必要在每次调用的时候都new 一个对象,因为那样开销会比较大。解决办法就是:创建好一个对象后,一直放在那里,什么时候有需要再get就行了。
以读写配置文件为例,下面介绍两种经典的用法:
1、饿汉模式
package SingleInstance;
import java.io.*;
import java.util.*;
public class Configure {
private Configure() {} //私有化构造方法,确保不能通过new 创建
public static Configure get() {
return configure;
}
public Object read(String key) throws IOException {
Properties properties = new Properties();
properties.load(in);
return properties.get(key);
}
InputStream in = this.getClass().getResourceAsStream("/config.properties");
private static Configure configure = new Configure(); // 用static修饰,该对象只会在加载类的时候创建一次
}
特点:类被加载的时候就创建,且只会创建一次。如果创建之后 很久才使用,则前期会一直占用内存,因此优先考虑第二种方式。
2、懒汉模式(延迟加载)
package SingleInstance.lazy;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.locks.*;
public class Configure {
private Configure() {} //私有化构造方法,确保不能通过new 创建
public static Configure get() {
if(configure != null) {
return configure;
}
lock.lock(); //加锁,确保线程安全
try {
if(configure == null) {
configure = new Configure();
}
}
finally { //finally修饰,释放锁资源
lock.unlock();
}
return configure;
}
public Object read(String key) throws IOException {
Properties properties = new Properties();
properties.load(in);
return properties.get(key);
}
private InputStream in = this.getClass().getResourceAsStream("/config.properties"); //配置文件 文件流
private static Lock lock = new ReentrantLock();
private static Configure configure;
}
优点:只有当get第一次调用的时候,才会创建该对象,节省内存。开发中基本使用的是这种方式