单例模式

一、核心作用

保证一个类只有一个实例,并且提供一个访问该实例,并且提供一个访问该实例的全局访问


二、常见的应用场景


三、常见的五种单例模式模式实现方式


-主要

饿汉式(线程安全,调用效率高,但是不能延时加载)

懒汉式(线程安全,调用效率不高,可以延时加载)

-其他

双重检测锁式(由于JVM底层内部模型的原因,偶尔会出问题,不建议使用)

静态内部式(线程安全,调用效率高。可以延时加载)

枚举单例(线程安全,调用效率高。不能延时加载)

四、如何选用


-单例对象 占用资源少,不需要延时加载

枚举式好于饿汉式

-单例对象 占用资源大,需要延时加载

静态内部式好于懒汉式


五、各种实现方式代码


package Singleton;
/***
 * 测试单例模式中  饿汉式
 * 1.线程安全
 * 2.线率高
 * 3.但是,不能延时加载
 * @author zw
 *
 */
public class SingletonDemo01 {
	//类初始化时,立即加载这个对象
	private static SingletonDemo01 instance = new SingletonDemo01();
	
	private SingletonDemo01() {
		
	}
	
	
	public static SingletonDemo01 getInstance() {
		return instance;
	}
}

package Singleton;
/***
 * 测试单例模式中  懒汉式
 * 1.线程安全
 * 2.调用效率不高
 * 3.但是,keyi 延时加载
 * @author zw
 *
 */
public class SingletonDemo02 {

	private static SingletonDemo02 instance ;
	
	private SingletonDemo02() {
		
	}
	
	//如果不加synchronized,会导致线程不安全。在多线程中,会同时创建多个对象
	public static synchronized SingletonDemo02 getInstance() {
		if(instance == null) {
			instance =new SingletonDemo02();
			 return instance;
		}
		return instance;
	}
}

package Singleton;
/***
 * 静态内部类实现单例模式
 * 
 * 优点:线程安全,调用安全,并实现了延时加载
 * @author zw
 *
 */
public class SingletonDemo03 {
	private static class singletonClass{
		private static final SingletonDemo03 instance = new SingletonDemo03();
		
	}
	private SingletonDemo03(){
		
	}
	
	public SingletonDemo03 getInstance(){
		return singletonClass.instance;
	}
}
package Singleton;
/***
 * 测试枚举实现单例模式
 * 1.避免反射 反序列化 漏洞
 * 2.唯一 是没有懒加载
 * 
 * @author zw
 *
 */
public enum SingletonDemo04 {
	//这个枚举元素本身就是单例模式。
	INSTANCE;
	
}

反射,可以通过setAccessible(true)可以访问私有属性。反序列化,可以构造多个对象


package Singleton;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/***
 * 测试反射 反序列化访问漏洞
 * 
 * @author zw
 *
 */
public class App {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, Exception {
		SingletonDemo2 s1 = SingletonDemo2.getInstance();
		SingletonDemo2 s2 = SingletonDemo2.getInstance();
		System.out.println(s1);
		System.out.println(s2);
		
		
		//通过反射的方式直接调用私有构造器
//		Class clzz =Class.forName("Singleton.SingletonDemo2");
//		Constructor c =clzz.getDeclaredConstructor(null);
//		c.setAccessible(true);//跳过安全检查就可以访问私有属性
//		SingletonDemo02 s1 =(SingletonDemo02) c.newInstance(null);
//		SingletonDemo02 s2 =(SingletonDemo02) c.newInstance(null);
//		System.out.println(s1);
//		System.out.println(s2);
		
		//通过反序列化的方式构造多个对象
		
		FileOutputStream fos = new FileOutputStream("d:/test/a.txt");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(s1);
		oos.flush();
		oos.close();
		fos.close();
		
		ObjectInputStream ois = new ObjectInputStream(
				new FileInputStream("d:/test/a.txt"));
		SingletonDemo2 sdd =(SingletonDemo2) ois.readObject();
		System.out.println(sdd);
		
		
	}
}

通过以下方法可以防止这种漏洞

package Singleton;

import java.io.Serializable;

/***
 * 测试单例模式中  懒汉式
 * 1.线程安全
 * 2.调用效率不高
 * 3.但是,keyi 延时加载
 * @author zw
 *
 */
public class SingletonDemo2 implements Serializable{

	private static SingletonDemo2 instance ;
	
	private SingletonDemo2() {
		if(instance!=null) {
			throw new RuntimeException();
		}
		
	}
	
	//如果不加synchronized,会导致线程不安全。在多线程中,会同时创建多个对象
	public static synchronized SingletonDemo2 getInstance() {
		if(instance == null) {
			instance =new SingletonDemo2();
			 return instance;
		}
		return instance;
	}
	
	//反序列化如果定义了readResolve(),则直接返回此方法的指定对象。而不需要单独创建对象
	private Object readResolve() {
		return instance;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值