单例模式是使用最为普遍的模式之一。它属于创建模式,确保系统中该类型的类只被实例化一次。 也许有误解,认为单例是在jvm进程中只有一个实例,其实是在同一个Classloader下面仅被实例化一次。Singleton通常用来表示本质上唯一的系统组件,比如文件系统,窗口管理器,系统全局的配置之类的。 在Java语言中,单例能带来一些好处: 1. 对于频繁使用的对象,可以省略创建对象所花费的时间,特别对于重量级的对象,可以节省很大的开销。 2. 有new操作的次数减少,对内存的使用频率也会有所降低,减轻GC的负担。 让我们来看单例的一些实现:
实现方法(1):
- public class Singleton {
- private static final Singleton INSTANCE = new Singleton();
- private Singleton(){
- }
- public static Singleton getInstance(){
- return INSTANCE;
- }
- }
这种实现比较简洁,但无法做到延迟加载,因为instance是static的,实例化之类加载的时候就发生了。如果单例的创建过程非常慢,耗费资源,就可以考虑lazy-initialize的方式。
- public class Singleton {
- private static Singleton INSTANCE = null;
- private Singleton(){
- }
- public static synchronized Singleton getInstance(){
- if(INSTANCE == null){
- INSTANCE = new Singleton();
- }
- return INSTANCE;
- }
- }
让我们看一下改进的版本:
- public class Singleton {
- private Singleton(){
- }
- private static class SingletonHolder{
- private static Singleton INSTANCE = new Singleton();
- }
- public static synchronized Singleton getInstance(){
- return SingletonHolder.INSTANCE;
- }
- }
这种使用内部类的维护单例,确保只有SingletonHolder类被加载才会初始化,实例发生在加载时,对多线程友好。
上面的情形没有考虑到序列化问题,当Singleton实现了Serilaizable接口时,在反序列化阶段可能由于反射机制创建多个实例。为防止这种意外可以加上readResolve函数:
- private Object readResolve(){
- return SingletonHolder.INSTANCE;
- }
- public enum SingletonEnum {
- INSTANCE("name");
- private String name;
- private SingletonEnum(String name){
- this.name = name;
- }
- }