单例模式

与世无争的帅哥 提交于 2020-02-15 16:50:23

1.饿汉式(线程安全)

1.创建私有的静态的final修饰的常量,静态的,在类加载机制的(加载,连接,初始化,使用,卸载)步骤中的连接中的(验证,准备,解析)中的准备阶段就会给静态变量分配内存空间,但这个时候是默认值,初始值是在初始化过程中,新建该类对象

private static final 类 INSTANCE = new 类();

2.构造方法私有,如果我们不写,默认是无参,我们需该权限为private

 private(){
 }

3.提供获取对象方法,这样,外部就只能通过getInstance方法获取对象,并且这个对象是final修饰的。

publicgetInstance(){
	return INSTANCE;
}

这个时候有人提出来了,假如我不用这个对象,那在类加载的时候依然分配内存空间,岂不是空间浪费呢?其实我想说的是,你不用它,初始化它干啥?类只有在首次+主动使用(主动使用:反射,创建该类对象,调用该类静态方法或静态变量,初始化该类子类等等)才会触发初始化。不过为了解决这个问题,仍然有方案,请跟我来~~~~~~

2.懒汉式(线程不安全,在多线程下会new出多个对象,违背了单例原则,加锁)

public class{
	/*volatile关键字,JMM 修饰变量是变量的值在主内存里改变,主内存会告诉cpu,cpu重新读值。就好像线程通信。
	主内存的内容会被cpu执行的线程读取,但多个线程,有一个线程改变了主内存里的值,volatile关键字会起到通知
	其他线程的缓冲区,(线程执行的时候会把主内存里的某个值读取到自己的缓冲区里,然后不停的读取缓冲区里的
	值,如果是死循环,会一致重复下去,如果有睡眠或者其他闲置时间,这个线程可能会去主内存中在读取一次变量,
	但这个不确定,有问题有隐患。)做到同步。线程之间的可见性,无锁同步。对公共的变量+volatile,
	如果不加这个只能用synchronized,效率很低。*/
	private  volatile  static  类  instance = null;
	 
	//私有构造
	private 类(){}
	//加锁后获取对象方式
	public staticgetInstance(){
		if(instance==null){
			synchronized(.class){
				//双重判断的重要性,在上层判断的时候,可能会有多个线程满足,线程并发,违背单例
				if(instance==null){
						instance=new 类();
				}
			}
		}

		return instance;
	}

}

这样呢,是解决了初始化就创建对象的内存浪费问题,只有在我们调用getInstance方法的时候才会创建对象,但是加锁会使效率降低,那怎么办呢?? 跟我来~~~~~

3.静态内部类实现方法(类加载内部类不会被初始化,只有外部调用静态方法,静态方法里有静态内部类的对象初始化的时候,才会初始化内部类,同时创建了静态内部类中的创建外部类的对象)

public class{
	private static class 单例{
	//内部类可以访问外部类,外部类访问内部类需要创建内部类对象才可以。
		private static final 类 INSTANCE = new 类(); 
	}
	//对外提供访问内部类获得对象的方法
	public 类 getInstance(){
		return  单例.INSTANCE; 
	}
}

4.枚举实现单例模式

public enum ObjInstance{
	INSTANCE;
	private Obj obj = null;
	private ObjInstance(){
    	obj = new Obj();
    }
	public Obj getInstance(){
			return obj;
	}

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!