java单例,真的单吗?

说起单例肯定会想起,懒汉,饿汉。但是那都不是完美的。
但是还是要说一下的。
首先Singleton 指的就是被实例化一次的类。在spring ioc 容器中初始化bean的时候默认就是单例的。

饿汉
在程序加载的时候开销比较大,如果没有用到很浪费资源

public class ESingleTon(){
	private static final ESingleTon instance=new ESingleTon();
	private ESingleTon (){}
	public static ESingleTon getInstance(){
		return instance;
	}
}

懒汉

public class LSingleTon(){
	private static LSingleTon instance=null;
	private LSingleTon(){}
	public  static LSingleTon getInstance(){
		if(instance!=null){
		return instance;
	}
//这里为什么要加锁,因为在多线程情况下由于上面的判断不是原子性的所以会产生都是null 的判断。为什么不在方法上加内置锁呢。因为 getInstance()会被多次调用,每次都进入锁其他的线程会被阻塞。所以性能不好。
	synchronized(LSingleTon.class){
		if(instance!=null){
			return instance;
		}
		instance = new LSingleTon();
		return instance;
	}	
}

-------------------------------------------------这是华丽的分割线-------------------------------------------------------
上面是是常用的单例的实现方法,但是为什么说不完美呢。其实在一些情况下并不能保证单例。(序列化,反射)

首先说序列化

 @Test
    public void testLSingleTon() throws IOException, ClassNotFoundException {
        LSingleTon singleTon=LSingleTon.getInstance();
        ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("E:/test/test.class"));
        outputStream.writeObject(singleTon);
        System.out.println("new: "+singleTon.toString());
        ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("E:/test/test.class"));
        System.out.println("objinput: "+objectInputStream.readObject().toString());
    }
class LSingleTon implements Serializable{
    private static final long serialVersionUID = 1L;
    private static transient LSingleTon instance=null;

    private Object readResolve(){
        return instance;
    }

    private LSingleTon(){
        System.out.println("constructor: "+this);
    }
    public static LSingleTon getInstance(){
        if(instance!=null){
            return instance;
        }
//这里为什么要加锁,因为在多线程情况下由于上面的判断不是原子性的所以会产生都是null 的判断。为什么不在方法上加内置锁呢。因为 getInstance()会被多次调用,每次都进入锁其他的线程会被阻塞。所以性能不好。
        synchronized(LSingleTon.class){
            if(instance!=null){
                return instance;
            }
            instance = new LSingleTon();
            return instance;
        }
    }
}

在这里插入图片描述

可以看到 下面两个对象地址是不一样 的。所以单利失败。
那怎么办呢
序列化的类中有一个方法被我注释,只要打开就可以了。
只要序列化和反序列化公用一个jvm 堆栈,那么就可以取到相同的对象。
在这里插入图片描述
这样就OK了。

反射破环单例
这个很好理解,只要调用newInstance()就可以常见新的对象。这怎么办?
先看一下newinstance()的源码

在这里插入图片描述
这里判断是不是enum 如果是 不能创建enum objects ,反射是无法newInstance()来创建枚举对象的。

那只要是枚举就行了吗。NO
一个枚举类型的类 编译器 编译以后就是一个 class extends Enum{}
可以看到有一个 静态代码块
用来创建这个类的对象的,而且是根据有多少个enum元素就创建多少个对象对象的引用变量就是enum 中定义的元素名。
所以不能有多个enum 元素,只能有一个 就是一个单例子。

像这样 就OK了
public enum LSingleTon{
instance;

…类的其他属性
}

Java类中可以存在多个实方法。实方法是属于类的对象的方法,它可以操作对象的属性和执行特定的业务逻辑。多个实方法可以为类提供更丰富的功能,每个方法可以完成不同的任务。 以下是一个包含多个实方法的Java类示: ```java class MyClass { private int value; public MyClass(int value) { this.value = value; } // 第一个实方法:获取value的值 public int getValue() { return value; } // 第二个实方法:设置value的值 public void setValue(int value) { this.value = value; } // 第三个实方法:对value进行平方操作 public int squareValue() { return value * value; } } ``` 多个实方法不会破坏单例设计模式单例设计模式的核心是确保一个类在整个应用程序中只有一个实,并提供一个全局访问点来获取该实模式的实现主要依赖于私有构造方法、静态实引用和全局访问方法(通常是`getInstance()`),而与类中实方法的数量无关[^1]。 以下是一个使用双重检查锁定实现的模式示,包含多个实方法: ```java public class Singleton { private static volatile Singleton instance; private int data; private Singleton() { this.data = 0; } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } // 第一个实方法:获取data的值 public int getData() { return data; } // 第二个实方法:设置data的值 public void setData(int data) { this.data = data; } // 第三个实方法:对data进行加1操作 public void incrementData() { this.data++; } } ``` 在上述示中,`Singleton`类是一个类,无论调用多少个实方法,整个应用程序中始终只有一个`Singleton`实
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值