------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
单例设计模式
设计模式:解决某一类问题行之有效的方法。Java中有23中设计模式。
单例设计模式:解决一个类在内存中只存在一个对象。
想要保证一个类在内存中对象的唯一:
1.为了避免其他程序过多的建立该类对象,先禁止其他程序建立该类的对象。
2.还为了让其他程序可以访问到对象,只好在本类中自定义一个对对象。
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
单例设计模式三步骤:
1.将构造函数私有化。
2.在类中创建一个本类对象。
3.提供一个方法可以获取到该对象。
(对于事物怎么描述,还怎么描述。
当需要将该事物的对象保证在内存中唯一时,就将以上三步加上即可。)
单例模式根据实例化对象时机的不同分为两种:一种是饿汉式,一种是懒汉式。
单例设计模式的第一种方法:是先初始化对象,类进入内存时就已近存在对象,昵称为“饿汉式”。
单例设计模式的第二种方法:类进入内存时还没有存在对象,只有当调用get类方法时才才初始化对象,也叫做对象的延时加载,昵称为“懒汉式”。
class student
{
private int age;
//第一种方式:饿汉式
/*
//创建本类对象
private static student s=newstudent();
//私有化构造函数
private student(){}
//返回本类对象,该对象只存在一个。
public static student getstudent()
{
return s;
}
*/
//第二种方式:懒汉式
//student类进内存,对象还没有存在,只能调用了getinstance方法时,才建立对象。
/*
//创建本类对象
private static student s= null;
//私有化构造函数
private student(){}
//返回本类对象,该对象只存在一个。
public static student getstudent()
{
if(s == null)
p = new student();
return s;
}
*/
public void setAge(int age)
{
this.age=age;
}
public int getAge()
{
return age;
}
}
class demo
{
public static void main(string[] args)
{
student s1=student.getstudent();
student s2=student.genstudent();
s1.setAge(20);
s2.setAge(23);
//输出结果都是23,因为p1和p2都指向同一个对象
System.out.println(s1.getAge());
System.out.println(s2.getAge());
}
}
记录原则:定义单例,建议使用饿汉式。
饿汉式和懒汉式的区别:饿汉式单列在单列类被加载时候,就实例化一个对象给自己的引用。而懒汉式在调用取得实例方法的时候才会实例化对象。
在开发过程中,一般使用第一种方法,即“饿汉式”。因为第二种方法存在安全问题(当多个人同时调用该方法时,会存在安全问题)。
懒汉式单例在实际开发中不常用,但是在面试中常见。
多线程懒汉式单例设计:
分析:多线程懒汉式单例设计中,会出现问题的代码位于getInstance方法中。因为当对象称都判断
因为当多个线程都判断s==null,执行s==null后,由于为获取cup执行权,停止在new Single之前,当获取cup执行权后,所有的线程都会执行new Single(),造成对象不唯一。
如下:
classSingle{
private static Singles = null;
public Single(){}
public static Single getInstance() {
if(s ==null)
s = new Single();
return s;
}
}
在getInstance方法添加同步关键字,变成同步函数。但是如果改为同步函数后,会造成效率低。
如:if(s == null)
s = new Single();
但若改为同步代码块,效率也比较低,因为每次都要判断锁。
如:public static Single getInstance() {
synchronized(Single.class) {
if(s == null)
s = new Single();
}
return s;
}
所以可以选择双重判断,提高效率。当第1、2线程进入s=null,第1个线程获得锁,第2个线程被锁在外面,所以第1个线程创建s=new Single()对象。
当第2个线程获取cup执行权后,s不为空,所以不执行创建对象语句。当猴续的进城执行getInstance方法后,s不为空,所以不执行下面的语句,直接return s。
如下:
public static Single getInstance() {
if(s == null) {
synchronized (Single.class){
if(s == null)
s = new Single();
}
return s;
}
总结:多线程懒汉式单例设计模式的特点时,双重判断加代码同步(synchronized)。多线程中懒汉式单例设计模式的锁是该类的字节码文件对象。