首页 > 编程语言 > 详细

JAVA设计模式之单例模式详解

时间:2019-06-21 00:51:33      阅读:53      评论:0      收藏:0      [点我收藏+]

标签:饿汉   ava   我想   修改   时间片   区别   public   设计思想   只有一个   

什么是单例模式

但是模式是在软件编程中常见的一种设计模式,并且是代码量很少的一种,这中设计模式并不是只限制于一种语言,这是在无数前辈哪里总结出来的一种软件设计思想,顾名思义单例模式在系统中只有一个实例化的对象,正如他的名字一样只有一个,单例模式最初出现在《设计模式》:保证一个类只有一个实例,并且提供一个访问他的全局访问点。

单例模式分为哪几种

1.饿汉式

2.懒汉式

3.最后我还要说下在多线程的模式下如何保证只能实例一个对象

饿汉式写法

饿汉式写法我想应该理解成像一个饥饿的汉子一样,不管在实际的情况需不需要创建这个类的对象,总之在第一次使用该类的时候就创建一个对象引用

如何写?我这里总结的3个步骤:

  1. 私有化构造方法
  2. 提供一个公共的方法,这个方法可以返回该类的实例对象
  3. 创建一个私有化的静态的类的对象 

    问:为什么要设置私有化的静态类对象?

    答:如果这里的对象时公有的那么我们可以通过在外界类名.对象名的修改这个对象,虽然说我们的构造方法是私有的我们不能new一个对象,但是我们可以将此设置为空,像下图似的如果是公有的就可以在外界修改了,这样很危险,所以这里要设置成私有的。

技术分享图片

接下来我们看下代码如何编写和检测是否是整个程序只有一个对象

class A{

	//创建一个私有静态的类对象
	private static A a = new A();
	//私有化构造
	private A() {
		System.out.println("创建了一个A的实例对象");
	}
	//提供一个共有的可以返回类对象的方法
	public static A getSingleton() {
		return a;
	}
}

在外界调用getSingleton方法来获取创建的对象

A.getSingleton();

接下来测试下是否只是创建了一个对象,我们这里通过For循环连续调用getSingleton方法,我在A类的构造方法里输出了一句话如果是创建了多个对象,肯定会多次输出这句话

public static void main(String[] args) {
	for(int i = 0 ;i <500;i++) {
		A.getSingleton();
	}
}

测试是否只有一个对象被实例化,结果输出如下,以此证明这样我们在整个程序中只是创建了一个对象

技术分享图片

懒汉式写法

懒汉式写法可能是说这个程序比较懒吧,只有需要的时候他才实例化一个对象,这个部分代码是和饿汉式差不多的,只是在实例化对象的时候有所区别,懒汉式写法的步骤如下:

  1. 私有化构造方法
  2. 提供一个公共的方法,这个方法可以返回该类的实例对象
  3. 创建一个私有化的静态的类的对象   这里创建类的对象的时候不要直接new出来
  4. 在我们的返回对象的公共方法中写一个判空的处理

 来看下代码如何实现的

class A{

	//创建一个私有静态的类对象
	private static A a = null;
	//私有化构造
	private A() {
		System.out.println("创建了一个A的实例对象");
	}
	//提供一个共有的可以返回类对象的方法
	public static A getSingleton() {
		if(a == null) {
			a = new A();
		}
		return a;
	}
}

懒汉式的调用方法和饿汉式的一样

A.getSingleton();

这里我们也是通过for循环来测试下是否只有一个对象被实例化

public static void main(String[] args) {
	for(int i = 0 ;i <500;i++) {
		A.getSingleton();
	}
}

打印结果

技术分享图片

在多线程中懒汉式写法出现的问题

public static void main(String[] args) {
	for(int i = 0 ;i <500;i++) {
		Thread thread = new Thread(()->{
			A.getSingleton();
		});
		thread.start();
	}
}

这是我们通过多线程来获取到的A类的对象,来看下打印出的结果,这里并没有像上面的写法中显示的结果一样,而是创建了好多的实例对象

技术分享图片

在学习了多线程的朋友应该了解到,其实所谓的并发,并不是真正的并发,而是通过时间片的轮转来使用cpu的资源,而这里的问题就出现在了判空处理的代码中

技术分享图片

这里画个图来解释下:

技术分享图片

解决这一问题我们需要用到了多线程中的synchronized关键字同步方法,这里要看清楚,因为这里的公共方法是static静态的方法,所以这里的同步监视器是指的A这个类,

这里使用同步方法可以看出是在操作系统中的临界资源,当一个数据正在被访问,会给这个数据加一把锁,有锁的数据只能同时被一个进行所访问,其他的线程只能等待,只有这个线程释放了这把锁其他的线程才可以访问,这样我下面这些代码在做判空处理的时候就不会出现错误。

class A{

	//创建一个私有静态的类对象
	private static A a = null;
	//私有化构造
	private A() {
		System.out.println("创建了一个A的实例对象");
	}
	//提供一个共有的可以返回类对象的方法
	public synchronized static A getSingleton() {
		if(a == null) {
			a = new A();
		}
		return a;
	}
}

同样这里使用for循环在多线程下来检测下是否可以

public static void main(String[] args) {
	for(int i = 0 ;i <500;i++) {
		Thread thread = new Thread(()->{
			A.getSingleton();
		});
		thread.start();
	}
}

看下结果,这中情况只会出现在懒汉式的写法中,饿汉式是不会出现的。只要加个同步方法就可以了(这里的同步静态方法监视器是类)

技术分享图片

 

JAVA设计模式之单例模式详解

标签:饿汉   ava   我想   修改   时间片   区别   public   设计思想   只有一个   

原文:https://www.cnblogs.com/mCarrYoung/p/11062200.html

(0)
(0)
   
举报
评论 一句话评论(0
0条  
登录后才能评论!
© 2014 bubuko.com 版权所有 鲁ICP备09046678号-4
打开技术之扣,分享程序人生!
             

鲁公网安备 37021202000002号