单例模式的特点:
由于单例模式只生产一个实力,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理
常见的五种单例模式实现方式:
主要:
一:饿汉式(线程安全,调用效率高,但是,不能延时加载)
二:懒汉式(线程安全,调用效率不高,但是,可以延时加载)
其他:
三:双重检测锁式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用)
四:静态内部类式(线程安全,调用效率高,但是,可以延时加载)
五:枚举单例(线程安全,调用效率高,不能延时加载)
如何选用单例:
单例对象占用资源少,不需要延时加载:枚举>饿汉式
单例对象占用资源大,需要延时加载:静态内部类式>懒汉式
饿汉式实现:
public class HungrySingleton {
private static /*final*/ HungrySingleton hs = new HungrySingleton();//类初始化时立即加载这个对象(缺少延时加载的优势)
private HungrySingleton() {}//私有化构造器
public static /*synchronized*/ HungrySingleton getInstance() {//不需要synchronized 因为是在类加载的时候会有线程安全的天 //然条件,所以不需要synchronized关键字,不需要synchronized //所以效率高
return hs;
}
}
public class Client {
public static void main(String[] args) {
HungrySingleton hs1 = HungrySingleton.getInstance();
HungrySingleton hs2 = HungrySingleton.getInstance();
System.out.println(hs1==hs2);//结果为true
}
}
饿汉式单例模式代码中,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题,可以省略synchronized关键字如果只是加载本类,而不是调用getInstance(),甚至永远没有调用,则会造成资源浪费!
懒汉式单例模式:
先创建一个ls属性,当调用懒加载方法的时候先去判断ls是否为空,如果为空则创建并返回ls,如果不为空表示已经存在直接返回
public class LazySingleton {
private static LazySingleton ls ;
private LazySingleton() {};//私有化构造器
public static synchronized LazySingleton getInstance() {
if (ls==null) {
ls = new LazySingleton();
}
return ls;
}
}
public class Client {
public static void main(String[] args) {
LazySingleton ls1 = LazySingleton.getInstance();
LazySingleton ls2 = LazySingleton.getInstance();
System.out.println(ls1 == ls2);//结果为true
}
}
要点:
lazy load 具有延迟加载 也就是说在真正用到的时候才加载
资源资源率高了,但是,每次调用getInstance()方法都要同步,并发效率较低