单例:
一个类只能有一个对象,保证项目访问的安全性。
优点:配合同步,保证安全性,共享机制,数据的共享。
缺点:降低并发性,耦合性增加。
单例三要素:
(1)构造方法私有
(2)静态的引用型全局变量
(3)提供静态的供外部访问的引用型方法
eg:
TestSingleton1.java
Singleton1.java Singleton2.java
内存图:
执行过程
执行主方法,(从左至右)
Singleton1 a1 = Singleton1.getInstance();
创建Singleton1的变量a1,还未进入栈。
加载Singleton1.class进内存,静态全局变量(私有的),在方法区的静态数据区为静态全局变量开辟空间,四个字节instance(Singleton1类型),
初始化:instance(Singleton1类型)存放Singleton1对象,在堆里创建Singleton1对象,属性空间count(实例全局变量,值0),方法空间getCount()。
Singleton1有静态全局变量,(具有静态全局变量的对象自动拥有静态全局变量的引用),名instance,调用构造方法(一个参数的),将10赋值给count,输出count的值,
创建完对象后,将对象的地址给静态全局变量,(此时形成环,对象拥有静态全局变量的引用,静态全局变量存放对象的地址),在栈里创建变量a1(Singleton1类型),
此时想得到对象,调用getInstance(),(不能用对象调用,因为还没有对象),所以它是静态的方法static,到instance拿,需公有(public),通过Singleton1这个类调用与其绑定的静态方法 getInstance(),返回方法区的静态数据区的静态全局变量,将此对象的地址传给a1,a1的值与instance相等,
Singleton1 a2 = Singleton1.getInstance();
创建Singleton1类型的引用型变量a2,不需要加载了,不再为静态全局变量开辟空间,调用Singleton1的getInstance(),返回instance(与Singleton1绑定),将此地址传给a2,(同一个对象的地址)。
用等值比较进行验证。System.out.println(“a2 == a1 is ” + (a1 == a2)); true
环:返回instance所指的instance属性,通过引用对象又回来了。说明具有静态全局变量的对象自动拥有静态全局变量的引用,
饥汉模式:
一加载字节码文件到方法区的静态数据区,为该类的静态全局变量instance,在静态数据区开辟空间,为其初始化(显式)。Singleton1对象创建:一加载类,就创建。
优点:
一加载类就创建对象
缺点:
容易造成内存泄露
饱汉模式:
一加载字节码文件到方法区的静态数据区,为该类的静态全局变量instance,在静态数据区开辟空间,为其初始化,值为null,未创建对象,用getInstance()前进行判断,if (sp==null)
则sp = new Singleton2();创建出此对象,并返回。以后再调用getInstance()时 ,不为null,则拿。
优点:第一次用才创建,对内存比较好。