JAVA单例模式详解

什么是单例模式

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

单例模式分为哪几种

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();
	}
}

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

 

转载于:https://www.cnblogs.com/mCarrYoung/p/11062200.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值