java单例模式和多例模式区别,java单例模式的好处

  java单例模式和多例模式区别,java单例模式的好处

  如何解决写爬虫IP受阻的问题?立即使用。

  【相关学习推荐:java基础教程】

  java单例模式区别是:

  一、懒汉式单例

  //惰性单例类。在第一次调用时实例化自身

  公共类Singleton {

  私有Singleton() {}

  私有静态Singleton single=null

  //静态工厂方法

  公共静态Singleton getInstance() {

  if (single==null) {

  single=new Singleton();

  }

  退单;

  }

  }

  通过将构造方法限制为私有,Singleton避免了类在外部被实例化。在同一个虚拟机中,Singleton的唯一实例只能通过getInstance()方法访问。

  (其实可以通过Java反射机制实例化一个构造函数为私有的类,这样基本会使所有的Java singleton实现失效。这个问题就不在这里讨论了。我们就当反射机制不存在吧。)

  但是上面的lazy Singleton的实现没有考虑线程安全,是不安全的。许多单例实例可能会出现在并发环境中。要实现线程安全,有以下三种方式,都是对getInstance的修改,以保证懒惰单例的线程安全。如果你是第一次接触singleton模式,对线程安全了解不多,可以先跳过下面三个小项,看看饥渴的singleton实例,以后再考虑线程。

  1、在getInstance方法上加同步

  公共静态同步单例getInstance() {

  if (single==null) {

  single=new Singleton();

  }

  退单;

  }

  2、双重检查锁定

  公共静态Singleton getInstance() {

  if (singleton==null) {

  synchronized (Singleton.class) {

  if (singleton==null) {

  Singleton=new Singleton();

  }

  }

  }

  返回单例;

  }

  3、静态内部类

  公共类Singleton {

  私有静态类LazyHolder {

  private static final Singleton实例=new Singleton();

  }

  私有Singleton (){}

  public static final Singleton getInstance(){

  返回懒汉。实例;

  }

  }这比上面的1和2更好,既实现了线程安全,又避免了同步带来的性能影响。

  二、饿汉式单例

  //饥饿的中国独生子女类。当类被初始化时,它已经被自己实例化了。

  公共类Singleton1 {

  私有Singleton1() {}

  私有静态final singleton 1 single=new singleton 1();

  //静态工厂方法

  公共静态Singleton1 getInstance() {

  退单;

  }

  } Hungry-Chinese style在创建类的同时已经创建了一个静态对象供系统使用,以后也不会改变,所以天生就是线程安全的。

  三、登记式单例(可忽略)

  //类似Spring中的方法,注册类名,下次直接从中获取。

  公共类Singleton3 {

  私有静态MapString,Singleton3 map=new HashMapString,singleton 3();

  静态{

  singleton 3 single=new singleton 3();

  map.put(single.getClass()。getName(),single);

  }

  //保护的默认构造函数

  受保护的Singleton3(){}

  //静态工厂方法,返回该类的唯一实例。

  公共静态Singleton3 getInstance(字符串名称){

  if(name==null) {

  name=singleton 3 . class . getname();

  system . out . println( name==null -name= name);

  }

  if(map.get(name)==null) {

  尝试{

  map.put(name,(Singleton3) Class.forName(name)。new instance());

  } catch(instantiation exception e){

  e . printstacktrace();

  } catch(IllegalAccessException e){

  e . printstacktrace();

  } catch(ClassNotFoundException e){

  e . printstacktrace();

  }

  }

  返回map.get(名称);

  }

  //示意性的业务方法

  公共字符串about() {

  返回“你好,我是RegSingleton。”;

  }

  公共静态void main(String[] args) {

  singleton 3 single 3=singleton 3 . getinstance(null);

  system . out . println(single 3 . about());

  }

  }注册的singleton实际上维护了一组singleton类的实例,这些实例存储在一个Map(注册簿)中。对于已注册的实例,它们直接从Map返回,而对于未注册的实例,它们先注册再返回。

  在这里,我将注册的singleton标记为可以忽略。从我的理解来说,首先是用的比较少。另外,其实内部实现还是用的饿单例,因为静态方法块,它的单例在类加载的时候就被实例化了。

  四、饿汉式和懒汉式区别

  饥饿的人和懒惰的人,

  Hungry的意思是,一旦类被加载,singleton就被初始化,以确保getInstance有保证时,singleton已经存在。

  另一方面,懒人很懒,只在getInstance被调用时才回去初始化这个singleton。

  以下两种方式的区别在于以下两点:

  1、螺纹安全:

  中文本来就是线程安全的,可以直接用于多线程没有问题。

  懒惰风格本身是非线程安全的。有几种方法可以实现线程安全,分别是上面的1、2和3。这三种实现在资源加载和性能上略有不同。

  2.资源加载和性能:

  Hungry type在创建类的同时实例化一个静态对象,不管后面是否会用到这个singleton,都会占用一定的内存,但是相应的,第一次调用的时候会更快,因为它的资源已经初始化了。

  顾名思义,惰性类型会延迟加载,对象会在第一次使用singleton时被实例化。第一次调用singleton时,需要对它进行初始化。如果有更多的工作要做,表现就会有些延迟,然后就和饿型一样了。

  至于1,2和3,有一些区别,

  首先,同步被添加到方法调用中。虽然线程是安全的,但是每次都要同步,会影响性能。毕竟,99%的情况不需要同步。

  其次,在getInstance中做了两次null检查,保证了只有第一次调用singleton,这是线程安全的,避免了每次同步的性能损失。

  第三,使用classloader的机制,保证初始化实例时只有一个线程,所以也是线程安全的,没有性能损失,所以一般我更喜欢用这个。

  这就是java和singleton模式之间区别的细节。更多详情请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: