JAVA单例设计模式(饿汉式和懒汉式)

单例设计模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

两种模式

  • 饿汉式
  • 懒汉式

1.1 饿汉式

一个类只能创建一个对象

  • 私有化构造器 private
  • 在类的内部创建一个类的实例,且为static
  • 私有化对象,通过公共方法调用
  • 此公共方法只能通过类来调用,因为设置的是static,同时类的实例也是static
//饿汉式
class Single
{    
    //私有化构造器 private
    private Single() {}
    //在类的内部创建一个类的实例,且为static
	private static final Single s = new Single();
	//私有化对象,通过公共方法调用
	public static Single getInstance()
	{
		return s;
	}
}

这是单例模式,一般用于比较大,复杂的对象,只初始化一次,有一个private的构造函数,使得不能用new来实例化对象,只能调用getInstance方法来得到对象,而getInstance保证了每次调用都返回相同的对象。

new 和 getInstance区别

1. new的使用:
如Object _object = new Object(),这时候,就必须要知道有第二个Object的存在,而第二个Object也常常是在当前的应用程序域中的,可以被直接调用的
简单来说,new就是通过生产一个新的实例对象,或者在栈上声明一个对象,每部分的调用,用的都是一个新的对象。 
2. GetInstance的使用:
* 在主函数开始时调用,返回一个实例化对象,此对象是static的,在内存中保留着它的引用,即内存中有一块区域专门用来存放静态方法和变量,可以直接使用,调用多次返回同一个对象。
* 对象使用之前通过getInstance得到而不需要自己定义,用完之后不需要delete;
* new 一定要生成一个新对象,分配内存;getInstance() 则不一定要再次创建,它可以把一个已存在的引用给你使用,这在效能上优于new* new创建后只能当次使用,而getInstance()可以跨栈区域使用,或者远程跨区域使用。所以getInstance()通常是创建static静态实例方法的。
* getInstance这个方法在单例模式用的甚多,为了避免对内存造成浪费,直到需要实例化该类的时候才将其实例化,所以getInstance来获取该对象。
* 注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

1.2 懒汉式

  • 私有化构造器
  • 创建一个私有的实例static 先不实例化为 null
  • 通过公共方法调用 static 在方法里面进行判断,if = null 实例化 !=null 直接return
class Single{
        //1.私有化构造器
        private Single() {}
        //2.创建一个私有的实例为static 且值设置为null
   	    private static Single s=null;
        //3.通过公共方法调用,static
    	public static Single getInstance()
        	if(s==null)
        	{
            s=new Single();
            }
        return s;
    }
}
 

2.1 线程安全问题

  1. 饿汉式:是安全的,可以直接用于多线程而不会出现问题。

  2. 懒汉式:是不安全的,可以使用同步锁synchronized解决。

2.2 解决多线程中懒汉式的不安全问题

不安全情况:

//懒汉式
class Single
{
	private static Single s=null;
	private Single() {}
	
	public static Single getInstance()
	{
				if(s==null)
				{
					//--A A线程进入
					//--B B线程进入
          /*由于s==null判断一直为真,线程可以一直进入
            此时线程不安全,不是单例模式。
          */
					s=new Single();
				}
		
	}
	return s;
	
    }

解决办法:加入同步锁

//懒汉式
class Single
{
	private static Single s=null;
	private Single() {}
	
	public static Single getInstance()
	{
		if(s==null)
		{
			synchronized (Single.class) {
				
				if(s==null)
				{
					//--A
	/* 使用synchronized可以在一个线程A进入后关闭入口
	而当一个线程A进入后s!=null,实现单例模式
	此处使用双重if判断,可以减少判断锁的次数,
	提高了懒汉式的效率。
					*/
					s=new Single();
				}
			}
		}
	}
	return s;
	
    }

饿汉式和懒汉式的对比

  1. 饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。
  1. 懒汉式,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值