01
单例模式介绍
02
懒汉式与饿汉式懒汉式与饿汉式
03
饿汉式单例模式实现
package com.qzq.singleton.type1;
public class SingleTonTest01 {
public static void main(String[] args) {
//测试
SingleTon instance1 = SingleTon.getInstance();
SingleTon instance2 = SingleTon.getInstance();
System.out.println(instance1==instance2);
}
}
//饿汉式写法
class SingleTon{
//1. 构造器私有化,外部无法new
private SingleTon(){
}
//2. 本类内部创建对象实例
private final static SingleTon instance = new SingleTon();
//3. 提供一个静态方法,来返回实例对象
public static SingleTon getInstance(){
return instance;
}
}
04
懒汉式单例模式实现
懒汉式单例模式重点在于线程安全问题。
synchronized Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
在代码中,synchronized() 括号中的是SingleTon这个类,表示锁定SingleTon类,此时其他线程执行到这里会陷入等待。
package com.qzq.singleton.type5;
public class SingleTonTest05 {
public static void main(String[] args) {
SingleTon instance1 = SingleTon.getInstance();
SingleTon instance2 = SingleTon.getInstance();
System.out.println(instance1==instance2);
}
}
class SingleTon{
//volatile保证可见性
private static volatile SingleTon instance;
private SingleTon(){}
//提供一个静态公用方法,当使用到该方法时,才去创建instance
//加入同步处理的代码,解决线程不安全问题
public static SingleTon getInstance(){
if(instance == null){
synchronized(SingleTon.class){
if(instance==null){
instance = new SingleTon();
}
}
}
return instance;
}
}
使用枚举方法防止反序列化重新创建新的对象。
除枚举方式外, 其他方法都会通过反射的方式破坏单例,反射是通过调用构造方法生成新的对象。使用枚举方法可以防止使用者通过反射来破坏单例模式。
package com.qzq.singleton.type7;
public class SingleTonTest7 {
public static void main(String[] args) throws InterruptedException {
System.out.println("hhh");
Thread.sleep(1000);
SingletonObject instance1 = SingletonObject.getInstance();
SingletonObject instance2 = SingletonObject.getInstance();
System.out.println(instance1==instance2);
}
}
class SingletonObject {
private SingletonObject(){
}
/**
* 枚举类型是线程安全的,并且只会装载一次
*/
private enum Singleton{
INSTANCE;
private final SingletonObject instance;
Singleton(){
System.out.println("loading");
instance = new SingletonObject();
}
private SingletonObject getInstance(){
return instance;
}
}
public static SingletonObject getInstance(){
return Singleton.INSTANCE.getInstance();
}
}
非枚举实现想要阻止单例破坏,可以在构造方法中进行判断,若已有实例, 则阻止生成新的实例,解决办法如下:
private SingletonObject1(){
if (instance !=null){
throw new RuntimeException("实例已经存在,请通过 getInstance()方法获取");
}
}
如果单例类实现了序列化接口Serializable, 就可以通过反序列化破坏单例,所以我们可以不实现序列化接口,如果非得实现序列化接口,可以重写反序列化方法readResolve(), 反序列化时直接返回相关单例对象:
public Object readResolve() throws ObjectStreamException {
return instance;
}
https://zhuanlan.zhihu.com/p/80127173
文章转载自山人彤,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。





