搜索
写经验 领红包
 > 社会

java中单例模式有几种怎么破坏单例模型的(单例模式写法java)

导语:Java中单例模式有几种,怎么破坏单例模式?

java中单例模式有几种怎么破坏单例模型的(单例模式写法java)

Java中单例模式有几种,怎么破坏单例模式?

问题背景

单例模式是日常工作中很常见的一种设计模式,但是越简单的往往坑越多,梳理一波,查漏补缺。

一、什么是单例模式?

单例模式就是确保项目里某个类最多只能有一个实例,而且向整个系统提供这个实例。

二、单例模式有哪几种?

(1)饿汉式单例模式

public class SingleDemo {

// 私有化构造方法使得该类无法在外部通过new进行实例化

private SingleDemo(){

}

// 准备一个类属性,指向一个实例化对象。因为是类属性,所以只有一个

private static SingleDemo instance = new SingleDemo();

//public static 方法,提供给调用者获取定义的对象

public static SingleDemo getInstance(){

return instance;

}

}

注意:在类加载时,已经自行实例化,可能需要考虑内存开销问题。

(2)懒汉式单例模式

提到懒汉式单例模式,很多同学容易写成以下这种:

// 私有化构造方法使得该类无法在外部通过new进行实例化

private SingleDemo(){

}

private static SingleDemo instance;

public static SingleDemo getInstanceA() {

if (null == instance) {

instance = new SingleDemo();

}

return instance;

}

此方式在单线程的时候工作正常,但在多线程的情况下就有问题了。如果两个线程同时运行到判断instance是否为null的if语句,并且instance的确没有被创建时,那么两个线程都会创建一个实例,此时就不再满足单例模式的要求了。

进一步优化,直接在getInstanceA()方法加上sychronized关键字,得到2.0版本,如下所示:

// 私有化构造方法使得该类无法在外部通过new进行实例化

private SingleDemo(){

}

private static SingleDemo instance;

public synchronized static SingleDemo getInstanceA() {

if (null == instance) {

instance = new SingleDemo();

}

return instance;

}

但每次调用getInstanceB()方法时都被synchronized关键字锁住了,会引起线程阻塞,影响程序的性能。然后加以改进,不让线程每次调用getInstanceC()方法时都加锁,而只是在实例未被创建时再加锁,得到3.0版本,如下所示:

// 私有化构造方法使得该类无法在外部通过new进行实例化

private SingleDemo(){

}

private static SingleDemo instance;

public static SingleDemo getInstance() {

// 先判断实例是否存在,若不存在再对类对象进行加锁处理

if (instance == null) {

synchronized (SingleDemo.class) {

instance = new SingleDemo();

}

}

return instance;

}

这样相比直接在方法上加synchronized关键字的2.0版本,确实效率提高了,不过这个还有个问题,如果有多个线程进入到 if (instance == null) 判断后,再竞争锁,可能就会产生多个实例,单例模式就失效了,也不符合。那么最后就进化到了版本4.0,也就是双重检验锁版本,如下所示:

// 私有化构造方法使得该类无法在外部通过new进行实例化

private SingleDemo(){

}

private static SingleDemo instance;

public static SingleDemo getInstance() {

// 先判断实例是否存在,若不存在再对类对象进行加锁处理

if (instance == null) {

synchronized (SingleDemo.class) {

if (instance == null) {

instance = new SingleDemo();

}

}

}

return instance;

}

(3)静态内部类方式(推荐)

加载一个类时,其内部类不会同时被加载。一个类被加载,当且仅当其某个静态成员(静态域、构造器、静态方法等)被调用时发生。 ——饿汉式对应的内存优化

由于静态内部类的特性,只有在其被第一次引用的时候才会被加载,所以可以保证其线程安全性。

实例如下:

// 私有化构造方法使得该类无法在外部通过new进行实例化

private SingleDemo(){

}

private static final class SingleDemoHolder {

private static final SingleDemo instance = new SingleDemo();

}

public static SingleDemo getInstance() {

// 先判断实例是否存在,若不存在再对类对象进行加锁处理

return SingleDemoHolder.instance;

}

(4)枚举方式(推荐)

enum Single {

SINGLE;

private Single() {

}

public void print() {

System.out.println(&34;);

}

}

创建枚举默认就是线程安全的,所以不需要担心double checked locking,而且还能防止反序列化导致重新创建新的对象。保证只有一个实例

三、怎么破坏单例模式?

私有化方法可以通过反射调用,这样就可以new出不止一个这个“单例类”的对象,即破坏了这个单例模式。

本文内容由小梓整理编辑!