设计模式之-单例模式(Singleton)及java中==与equals的区别

 

GOF中又一创建型模式,FOG中对单例的定义非常简单:

即:保证一个类只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。

在应用系统开发中,我们常常有以下需求:

- 在多个线程之间,比如servlet环境,共享同一个资源或者操作同一个对象

- 在整个程序空间使用全局变量,共享资源

- 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。

 

这样使用单例就非常合适了

 

 

单例分为

1、恶汉式

2、懒汉式

3、双重检查(有问题,后面会简单描述)

 

 

首先来看恶汉式:

 

定义一个Person类,并不允许使用new关键字创建对象

 

 

public class Person {

       //声明一个静态的常量引用Person实例

       private final static Person person = new Person();

       private Person(){}

      

       private String name;

       public static Person getPerson() {

           return person;

       }

      

       public String getName() {

           return name;

       }

 

       public void setName(String name) {

           this.name = name;

       }

       //通过一个getInstance得到person的实例对象

       public static Person  getInstance(){

           return person;

       }

      

      

}

 

 

 

 

懒汉式单例:

 

 

 

public class Person1 {

       private  static Person1 person ;

       private Person1(){}

      

       private String name;

       public static Person1 getPerson() {

           return person;

       }

      

       public String getName() {

           return name;

       }

 

       public void setName(String name) {

           this.name = name;

       }

       //加上一个锁以防多线程访问

       public static synchronized Person1  getInstance(){

           //如果person未初始化则new一个对象

           if(person==null){

              person = new Person1();

           }

          

           return person;

       }

      

      

}

 

因为懒汉式在多线程并发访问时可能会出现同时几个线程进入getInstance结果会new出多个对象,所以加上synchrinized锁住,防止多线程访问问题,但是这样写的话每一个线程进来都会等待另一个线程执行完毕,所以效率并不是很好

 

 

 

那么继续看第三种:双重检查

 

 

 

public class Person2 {

       private  static Person2 person ;

       private Person2(){}

      

       private String name;

       public static Person2 getPerson() {

           return person;

       }

      

       public String getName() {

           return name;

       }

 

       public void setName(String name) {

           this.name = name;

       }

   

       public static Person2  getInstance(){

           //如果person未初始化则new一个对象

            if(person==null){

          

           synchronized(Person.class){

               

              if(person==null){

                  person = new Person2();

              }

              }

            }

           return person;

       }

      

      

}

 

 

将synchronized加在if语句里面,这样如果person被初始化了就不会进入锁里面了,但是为什么要加双重检查呢,假如两个线程同时进入if语句中第一个线程执行锁里面的代码后第二个还回继续执行,这样再加一次判断那么就无法执行了,从理论上来说这是一个非常好的方式

,但是实际上是有问题的

 

这跟内存模型允许所谓的无序写入有关,这里不再多说,关于无序写入请参考其他资料

最后是测试:

    Person person = Person.getInstance();

           Person person1 = Person.getInstance();

 

       System.out.println(person.equals(person1));

 

 

 

这里顺便总结一些==与equals的区别:

对于简单的值类型的值在java中一般存放在栈中,对引用型类型则是将引用的变量放到栈中,变量储存的仅仅是引用类型的地址,其值却放在堆中

对于简单值类型,==只是比的两个值是否相等,对于引用型变量==比较的只是两个变量在堆中储存的地址是否相同,即栈中的值是否相同,equals比较的是两个操作是否引用的同一个变量,即堆中的值是否相同

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值