前言:不断学习就是程序员的宿命
所谓的单例设计模式,就是采取一定的方法保证整个的软件系统中,对某个类只能存在一个对象实例,并且该类只能提供一个取得对象实例的方法(静态方法)。比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建session对象。SessionFactory并不是轻量级的
单例模式有以下8种方式:
public class Singleton01 { //本类内部创建对象实例 private final static Singleton01 instance=new Singleton01(); //构造器私有化,外部不能new private Singleton01(){} //提供一个公有静态方法,返回实例对象 private static Singleton01 getInstance(){ return instance; } public static void main(String[] args) { //测试 Singleton01 instance1 = Singleton01.getInstance(); Singleton01 instance2 = Singleton01.getInstance(); System.out.println(instance1==instance2); System.out.println(instance1.hashCode()); System.out.println(instance1.hashCode()); } }
分析:
(1)优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
(2)缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费
public class Singleton02 { //本类内部创建对象实例 private static Singleton02 instance; //构造器私有化, 外部不能new private Singleton02(){} // 在静态代码块中,创建单例对象 static { instance = new Singleton02(); } //提供一个公有的静态方法,返回实例对象 public static Singleton02 getInstance() { return instance; } public static void main(String[] args) { //测试 Singleton02 instance = Singleton02.getInstance(); Singleton02 instance2 = Singleton02.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } }
分析:
(1)这种方式和上述方式类似,只不过将类实例化的过程放在了静态代码块中,也就是在装载的时候执行静态代码中的代码,初始化类的实例
(2)结论:单例方式可用,但可能会造成内存浪费
/** * @ClassName: Singleton03 * @Description: 懒汉式-线程不安全 * @Author: xiedong * @Date: 2020/4/5 0:19 */ public class Singleton03 { private static Singleton03 instance; private Singleton03() {} //提供一个静态的公有方法,当使用到该方法时,才去创建 instance public static Singleton03 getInstance() { if(instance == null) { instance = new Singleton03(); } return instance; } public static void main(String[] args) { System.out.println("懒汉式1 , 线程不安全~"); Singleton03 instance = Singleton03.getInstance(); Singleton03 instance2 = Singleton03.getInstance(); System.out.println(instance == instance2); // true System.out.println("instance.hashCode=" + instance.hashCode()); System.out.println("instance2.hashCode=" + instance2.hashCode()); } }
分析:
(1)起到了Lazy Loading的效果,但是只能在单线程下使用
(2)如果在多线程下,一个线程进入if(instance==null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例,所以在多线程环境下不可使用这种方式。
(3)结论:实际开发中,不要使用这种方式
原文:https://www.cnblogs.com/rmxd/p/12635430.html