定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
主要要素:
- 私有的构造方法。
- 指向自己实例的私有静态引用。
- 以自己实例为返回值的静态的共有方法。(返回的静态变量和方法是否静态没有关系)
单例模式根据实例化对象的时机的不同分为两种:
一种是饿汉模式单例,一种懒汉模式单例。
饿汉模式单例在类被加载的时候,就实例化一个对象交给自己的引用;
懒汉模式单例在调用取得实例方法的时候才会实例化对象。
饿汉式单例:代码如下:
public class Singleton{
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
懒汉式单例:代码如下:
public class Singleton2{
private static Singleton2 singleton ;
private Singleton2(){}
public static synchronized Singleton2 getInstance(){
if(singleton==null){
singleton = new Singleton2();
}
return singleton();
}
}
单例模式的优点:
- 在内存中只有一个对象,节省内存空间。
- 避免频繁的创建销毁对象,可以提高性能。
- 避免共享资源带的多重占用。
- 可以全局访问。
单例适用的场景:
- 需要频繁实例化然后销毁的对象。
- 创建对象时耗时过多或者好资源过多,但又经常用到的对象。
- 有状态的工具类对象。
- 频繁访问数据库或文件的对象。
- 以及其他没有用过的所有要求只有一个对象的场景。
单例模式注意事项:
- 只能使用单例类提供的方法得到单例对象,不要用反射,否则将会实例化一个新的对象。
- 不要做断开单例类对象与类中静态引用的危险操作。
- 多线程使用单例共享资源时,注意线程安全问题。
关于Java中的单例模式的一些争议:
若一个单例对象长时间不用,会被jvm认为是一个垃圾,在执行垃圾收集时候会被清理掉。对此说法有怀疑态度,观点为:
在hostpot虚拟机1.6版本中,除非认为的断开单例中的静态引用到单例对象的联接,否则jvm垃圾收集器不会回收单例对象
的。
在jvm 中会出现多个的单例吗?
在分布式系统中、多个类加载器、以及序列化的情况下会产生多个单例,这一点毋庸置疑的,在同一个jvm中,会不会残生
单例呢?使用getInstance()方法只能得到同一个单例,除非使用反射方式,将会得到新的单例。
Class c = Class.forNmae(Singleton.class.getName()); Constructor ct= c.getDeclaredConstructor(); ct.setAccessible(true); Singleton singleton =(Singleton)ct.newInstance();