黑马程序员_Singleton模式(单例模式)饿汉式和懒汉式

------- android培训、java培训、期待与您交流! ----------

单例设计模式

第一部分:

1、设计模式的概念:

每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次有一次地使用该方案而不必做重复劳动;而模式就是解决某一类问题最行之有效的方案;这是一个纯粹偏思想的,在不断的劳动的过程中总结出来的。

2、设计模式的特点:

2.1、将某一类问题解决起来会变的更简单;
2.2、让复杂的问题简单化;

3、单例设计模式:

解决一个类在内存中存在一个对象;换句话说就是在一个类中只能有一个对象,不可能会出现第二个对象;

4、单例设计模式的由来:

现在有两个程序,分别是A程序和B程序,当A程序要操作一个文件的时候,这是就要new一个对象,当B文件也要操作一个文件的时候,同样也要new一个新的对象,但是A和B操作的不是同一个对象,因此这时要保证对象的唯一性;

5、单例设计模式的思想:

5.1、为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象;
5.2、禁止其他的程序建立对象,由自己来建立对象;
5.3、为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象;
5.4、为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式;

6、单例设计模式的步骤:

6.1、将构造函数进行私有化;
6.2、在类中创建一个本类对象;
6.3、提供一个方法可以获取到该对象;

7、代码表现:

<span style="font-size:18px;">class Single
{
	private int num;
	public void setNum(int num)
	{
		this.num = num;
	}
	public int getNum()
	{
		return num;
	}
//	将构造函数进行私有化;
	private Single(){}
//	创建一个本类对象;
	private static Single s = new Single();
//	返回的是一个Single类型的对象;
	public static Single getInstance()//一个类类型的
	{
		return s;
	}

}
class SingleDemo 
{
	public static void main(String[] args) 
	{
//		类名调用静态方法
		Single s1 = Single.getInstance();
		Single s2 = Single.getInstance();
//		Single s1 = new Single();
//		Single s2 = new Single();
		s1.setNum(30);
		System.out.println(s2.getNum());
//		Single ss =Single.getInstance();
	}
}

/*
打印的是30,说明s1 和s2 指向的是同一个对象
*/</span><span style="font-size:24px;font-weight: bold;">
</span>

8、运行的结果:

设置的是s1的值是30,而打印的是s2的值也是30,由此可以s1和s2所指向的是同一个对象;

9、图形展示:


10、单例设计模式应用:

对于事物该怎么描述,还是怎么描述,当需要将该事物的对象保证在内存中唯一性时,就加入单例设计模式思想即可;

举例:

class Student
{
	private int age;//要将属性进行私有化
	public void setAge(int age)
	{
		this.age = age;
	}
	public int getAge()
	{
		return age;
	}
//	要求保证在内存中的唯一性,那么就加上下面的三步
	private Student(){}
	private static Student s = new Student();
	public static Student getInstance()
	{
		return s;
	}
}
class  SingleStudentDemo
{
	public static void main(String[] args) 
	{
//		调用静态方法;
		Student s1 = Student.getInstance();
		Student s2 = Student.getInstance();
		s1.setAge(34);
		System.out.println(s2.getAge());
	}
}

运行后的结果:


第二部分:

1、饿汉式

先初始化对象,开发一般会用饿汉式

2、饿汉式特点

2.1、Single类进内存,对象还没有存在,就已经创建好了对象;
2.1、安全,简单;

3.饿汉式代码体现

<span style="font-size:14px;">//第一种,这个是先初始化对象
//称为:饿汉式
class Single
{
	private Single(){}
	private static Single s = new Single();
	public static Single getInstance()
	{
		return s;
	}

}</span>

4、懒汉式

对象是方法被调用时,才初始化,也就做对象的延时加载;

5、延时加载

特点:Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象;
6、懒汉式的特点
刚开始不建立对象,如果什么时候需要,那么就什么时候建立对象;

7、懒汉式代码体现

//第二种,对象是方法调用时,才初始化,也叫做对象的延时加载,称为懒汉式
class Single 
{
	private Single(){}
	private static Single s =null;
	public static Single getInstance()
	{
		if(s==null)
		{
			synchronized(Single.class)
			{
				if(s==null)
					s = new Single();
			}
		}
		return s;
	}
}
class  SingleDemo
{
	public static void main(String[] args) 
	{
		Single ss = Single.getInstance();
	}
}

8、懒汉式的缺陷

8.1、缺陷:

如果遇到多线程时,当A程序读到getInstance的方法的时候,当cpu执行到s==null时,但是这时cpu切换到去处理B程序了,但是这时A程序就处于休息状态,没有执行程序,但是这时B程序同样也进来了,判断了s==null也是满足条件的,现在A程序醒了,然后执行了s = new Single();创建了一个对象,这是B程序也醒了,又创建了一个对象;换句话说就是现在内存中的对象已经不唯一了,懒汉式在多线程访问时会出现安全隐患;

8.2、措施:

在函数上加上一个锁就是Synchronized,这时如果A程序进来之后,但是B程序就不可以进入程序了,A程序创建了对象之后,然后返回了,这时B程序判断s已经不等于null,那么就不再执行程序了。但是在这个锁加载函数上面,每一个线程都要先进行判断一下,效率比较低效;这时如何能够既能可以保证对象的唯一性又能解决低效的问题?用双重判断来解决:判断锁的次数减少了;

9、面试

9.1、问:懒汉式和饿汉式有什么不同?
答:懒汉式的特点在于实例的延时加载。

9.2、问:懒汉式的延迟加载有没有问题?

答:有,如果多线程访问时,会出现安全问题。

9.3、问:出现了安全问题怎么解决?

答:可以加同步来解决,而加同步的方式有两种,同步代码快和同步函数都行,但是稍微有些低效,用双重判断的形式可以解决效率的问题。

9.4、问:加同步的时候使用的锁是哪一个?

答:该类所属的字节码文件对象。

第三部分

我的总结:

1、定义单例的时候建议使用饿汉式,因为饿汉式不会出问题,简单安全;
2、使用单例延时加载的时候,保证对象的唯一性,以及用双重判断来提高效率;
3、饿汉式的特点:对象先进行初始化;懒汉式的特点:对象后进行初始化;
4、懒汉式如何在多线程访问时解决安全隐患。
5、懒汉式的面试题;

发布了40 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/java9832/article/details/46392583
今日推荐