单例设计模式

1.饿汉式:类初始化时,会立即加载该对象,线程天生安全,调用效率高。(spring里面的是饿汉式)
2.懒汉式: 类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。
3.静态内部方式:结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。
4.枚举单例: 使用枚举实现单例模式 优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞, 缺点没有延迟加载。
5.双重检测锁方式 (因为JVM本质重排序的原因,可能会初始化多次,不推荐使用)

1. 饿汉式

天生线程安全(因为它一初始化就创建对象,其他线程只是读而不是写????如果写的话会怎样呢?也线程安全吗?应该要在声明对象的前面加上final修饰符吧)

//饿汉式
public class SingletonDemo01 {
	// 类初始化时,会立即加载该对象,线程天生安全,调用效率高
	private static SingletonDemo01 singletonDemo01 = new SingletonDemo01();   
	private SingletonDemo01() {
		System.out.println("SingletonDemo01初始化");
	}
	public static SingletonDemo01 getInstance() {
		System.out.println("getInstance");
		return singletonDemo01;
	}   
	public static void main(String[] args) {
		SingletonDemo01 s1 = SingletonDemo01.getInstance();
		SingletonDemo01 s2 = SingletonDemo01.getInstance();
		System.out.println(s1 == s2);
    	}
}

输出结果为true

2.懒汉式

//懒汉式
public class SingletonDemo02 
	//类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象。
	private static SingletonDemo02 singletonDemo02;
	private SingletonDemo02() { 
	}
	//加上synchronized之后,每次只能有一个线程进行访问,效率就降低了
	public synchronized static SingletonDemo02 getInstance() {
		if (singletonDemo02 == null) {
			singletonDemo02 = new SingletonDemo02();
		}
		return singletonDemo02;
	}
	public static void main(String[] args) {
		SingletonDemo02 s1 = SingletonDemo02.getInstance();
		SingletonDemo02 s2 = SingletonDemo02.getInstance();
		System.out.println(s1 == s2);
	}
}

3.枚举方式

什么是枚举(枚举这块知识还是不清晰)
枚举本身是单例的,一般用于项目中定义常量。

enum UserEnum {
	HTTP_200(200, "请求成功"),HTTP_500(500,"请求失败");
	private Integer code;
	private String name;
	UserEnum(Integer code, String name) {
		this.code = code;
		this.name = name;
	}
public Integer getCode() {
		return code;
	}
	public void setCode(Integer code) {
		this.code = code;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
public class TestEnum {
	public static void main(String[] args) {
		System.out.println(UserEnum.HTTP_500.getCode());
	}
}
/使用枚举实现单例模式 优点:实现简单、枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞 缺点没有延迟加载
public class User {
	public static User getInstance() {
		return SingletonDemo04.INSTANCE.getInstance();
	}
	private static enum SingletonDemo04 {
		INSTANCE;
		// 枚举元素为单例
		private User user;
		private SingletonDemo04() {
			System.out.println("SingletonDemo04");
			user = new User();
		}
		public User getInstance() {
			return user;
		}
	}
	public static void main(String[] args) {
		User u1 = User.getInstance();
		User u2 = User.getInstance();
		System.out.println(u1 == u2);
	}
}

4.双重检测锁

  public class SingletonDemo04 {
    	private SingletonDemo04 singletonDemo04;
    
    	private SingletonDemo04() {
    
    	}
    执行双重检查是因为,如果多个线程同时了通过了第一次检查,并且其中一个线程首先通过了第二次检查并实例化了对象,那么剩余通过了第一次检查的线程就不会再去实例化对象。
这样,除了初始化的时候会出现加锁的情况,后续的所有调用都会避免加锁而直接返回,解决了性能消耗的问题。
    	public SingletonDemo04 getInstance() {
    		if (singletonDemo04 == null) {
    			synchronized (this) {
    				if (singletonDemo04 == null) {
    					singletonDemo04 = new SingletonDemo04();
    				}
    			}
    		}
    		return singletonDemo04;
    	}
    }
posted @ 2018-10-09 13:10  抬头不见星空  阅读(20)  评论(0)    收藏  举报