多例模式

多例:只是单例的一种延伸   不必过于在意各种模式的名字,重要的是学会融会贯通,把生产的car放到集合中 类似JDBC 的连接池 把连接对象放到池中

多例模式特点:
     1. 多例类可以有多个实例
     2. 多例类必须自己创建自己的实例,并管理自己的实例,和向外界提供自己的实例

package com.pers.hoobey;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Car1 {
  private static Car1 car1 = new Car1();
  private static Car1 car2 = new Car1();
  private static List<Car1> list = new ArrayList<Car1>();//用于存放多个实例的car
  private static final int maxCount =2;//最多的实例数
  static{
    list.add(car1);
    list.add(car2);
  }
  private Car1(){}//私有构造方法 避免外部创建实例
/*
* @description 指定拿取某一个实例
*/
  public static Car1 getInstance(int index){
    return list.get(index);
  }
  //随机拿取实例
  public static Car1 getInstance(){
    Random random = new Random();
    int current = random.nextInt(maxCount);
    return list.get(current);
}
public void run(){
System.out.println("奔跑中的车.....");
}
}

顺便总结一下 普通工厂模式 工厂方法模式和抽象工厂模式的区别:

简单工厂是用来生产”东西“的,那任何”东西“的子类,比如汽车,自行车,轮船,洗发水都是可以被生产的,但此处简单工厂的压力太大了啊,任何”东西“的子类都可以被生产,负担太重,所以一般对简单工厂类也有种称呼,叫”上帝类“。
而工厂方法模式就很好的减轻了工厂类的负担,把某一类/某一种东西交由一个工厂生产,同时增加某一类”东西“并不需要修改工厂类,只需要添加生产这类”东西“的工厂即可,使得工厂类符合开放-封闭原则。
对于”东西“的分类,有时候不能光是横向的分类,从另一个角度也是可以分类的,不知道这句话的意思能不能懂,打个比方:汽车可以根据品牌分为奔驰、奥迪,也可以根据类别分为普通三厢车和SUV车,如果用工厂方法来描述的话,奔驰车工厂有一个方法即生产奔驰车,奥迪车工厂有一个方法生产奥迪车,但在有多重分类的情形下,这样写已经不够用,不符合实际了,这个时候需要用到抽象工厂模式,即奥迪车工厂有两个方法,一个方法是生产普通三厢奥迪车,另一个方法是生产SUV奥迪车。奔驰车工厂有两个方法,一个方法是生产普通三厢奔驰车,另一个方法是生产SUV奔驰车。
上面即工厂方法模式和抽象工厂模式的应用场景,因为这两者很像,所以概念上不容易区分,可以这么说,工厂方法模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂方法模式的一种推广。

再说下抽象工厂模式,此处的抽象工厂接口应该是有两个方法,一个是生成普通三厢车,一个是生产SUV车,可以说,生产的”东西“已经被限定住了,因此你不能生产某品牌汽车外的其他”东西“,因而可以理解成使用抽象工厂模式不能新增新的”东西“(在简单工厂和工厂方法中理论上都是可以新增任意”东西“的)

 

下面分析一下懒汉模式下的单例模式

作为一个单例,我们首先要确保的就是实例的“唯一性”,有很多因素会导致“唯一性”失效,它们包括:多线程、序列化、反射、克隆等,更特殊一点的情况还有:分布式系统、多个类加载器等等。其中,多线程问题最为突出。为了提高应用的工作效率,现如今我们的工程中基本上都会用到多线程;目前使用单线程能轻松完成的任务,日复一日,随着业务逻辑的复杂化、用户数量的递增,也有可能要被升级为多线程处理。所以任何在多线程下不能保证单个实例的单例模式,我都认为应该立即被弃用。

在只考虑一个类加载器的情况下,“饿汉方式”实现的单例(在系统运行起来装载类的时候就进行初始化实例的操作,由JVM虚拟机来保证一个类的初始化方法在多线程环境中被正确加锁和同步,所以)是线程安全的,而“懒汉”方式则需要注意了,先来看一种最简单的“懒汉方式”的单例:

这种写法只能在单线程下使用。如果是多线程,可能发生一个线程通过并进入了 if (singleton == null) 判断语句块,但还未来得及创建新的实例时,另一个线程也通过了这个判断语句,两个线程最终都进行了创建,导致多个实例的产生。所以在多线程环境下必须摒弃此方式。

除了多并发的情况,实现单例模式时另一个重要的考量因素是效率。前述的“懒汉方式”的多线程问题可以通过加上 synchronized 修饰符解决,但考虑到性能,一定不要简单粗暴地将其添加在如下位置:

上述方式通过为 getInstence() 方法增加 synchronized 关键字,迫使每个线程在进入这个方法前,要先等候别的线程离开该方法,即不会有两个线程可以同时进入此方法执行 new Singleton(),从而保证了单例的有效。但它的致命缺陷是效率太低了,每个线程每次执行 getInstance() 方法获取类的实例时,都会进行同步。而事实上实例创建完成后,同步就变为不必要的开销了,这样做在高并发下必然会拖垮性能。所以此方法虽然可行但也不推荐。那我们将同步方法改为同步代码块是不是就能减少同步对性能的影响了呢:

但是这种同步却并不能做到线程安全,同最初的懒汉模式一个道理,它可能产生多个实例,所以亦不可行。我们必须再增加一个单例不为空的判断来确保线程安全,也就是所谓的“双重检查锁定”(Double Check Lock(DCL))方式:

此方法的“Double-Check”体现在进行了两次 if (singleton == null) 的检查,这样既同步代码块保证了线程安全,同时实例化的代码也只会执行一次,实例化后同步操作不会再被执行,从而效率提升很多(详细比较见附录 1)。

双重检查锁定(DCL)方式也是延迟加载的,它唯一的问题是,由于Java 编译器允许处理器乱序执行,在JDK版本小于1.5时会有DCL失效的问题(原因解释详见附录 2)。当然,现在大家使用的JDK普遍都已超过1.4,只要在定义单例时加上1.5及以上版本具体化了的volatile关键字,即可保证执行的顺序,从而使单例起效。所以 DCL 方式是推荐的一种方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/541757.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle public view,【易错概念】以太坊Solidity函数的external/internal,public/private,view/pure/payable区别...

1. 函数类型&#xff1a;内部(internal)函数和外部(external)函数函数类型是一种表示函数的类型。可以将一个函数赋值给另一个函数类型的变量&#xff0c;也可以将一个函数作为参数进行传递&#xff0c;还能在函数调用中返回函数类型变量。 函数类型有两类&#xff1a;- 内部(i…

c-style字符字符串_C字符串-能力问题与解答

c-style字符字符串C programming String Aptitude Questions and Answers: In this section you will find C Aptitude Questions and Answers on Strings, String is the set of characters and String related Aptitude Questions and Answers you will find here. C编程Stri…

PHP Smarty template for website

/******************************************************************************* PHP Smarty template for website* 说明&#xff1a;* 之前一直在想将MVC的方式加在PHP做的网站上&#xff0c;这样比较好处理&#xff0c;相对来说比较好* 处理…

ftp连接oracle服务器,使用SSL加密连接FTP - 架建SSL安全加密的FTP服务器(图)_服务器应用_Linux公社-Linux系统门户网站...

四、使用SSL加密连接FTP启用Serv-U服务器的SSL功能后&#xff0c;就可以利用此功能安全传输数据了&#xff0c;但FTP客户端程序必须支持SSL功能才行。 如果我们直接使用IE浏览器进行登录则会出现图4显示的错误信息&#xff0c;一方面是以为没有修改默认的端口21为990&#xff0…

c# 情感倾向_C否则-能力倾向问题与解答

c# 情感倾向C programming if else Aptitude Questions and Answers: In this section you will find C Aptitude Questions and Answers on condition statements – if else, nested if else, ladder if else, conditional operators etc. C语言编程如果有问题&#xff0c;请…

springboot中使用缓存shiro-ehcache

在pom.xml中注入缓存依赖&#xff0c;版本(Sep 09, 2016)spring-context-support 包含支持UI模版&#xff08;Velocity&#xff0c;FreeMarker&#xff0c;JasperReports&#xff09;&#xff0c; 邮件服务&#xff0c; 脚本服务(JRuby)&#xff0c; 缓存Cache&#xff08;EHCa…

oracle 微信公众号,关于微信公众号贴代码的方法

微信公众号码上贴代码一直一来都是个头疼的问题。吐槽一句&#xff1a;要是后台编辑器支持markdown就好了。今天教大家用在线markdown排版工具&#xff0c;把代码完美贴到微信公众号上。长话短说&#xff0c;今天用到的两个工具&#xff1a;首先&#xff0c;以一段代码为例。假…

计算理论 形式语言与自动机_下推式自动机(PDA)| 计算理论

计算理论 形式语言与自动机Pushdown Automaton (PDA) is a kind of Automaton which comes under the theory of Computation that appoints stack. The word Pushdown stands due to the fact that the stack can be pushed down as operations can only work on the elements…

运维人员究竟如何提升价值,持续获得高薪?

作者简介&#xff1a;老男孩&#xff0c;北京老男孩IT教育创始人&#xff0c;17年IT经验&#xff0c;资深Linux实战专家&#xff0c;IT培训界实战派顶尖大师&#xff0c;国内将实战心理学体系大量注入IT运维培训领域的第一人&#xff0c;多本IT畅销图书作者&#xff0c;51CTO金…

Webservice soap wsdl区别之个人见解

Web Service实现业务诉求&#xff1a;Web Service是真正“办事”的那个&#xff0c;提供一种办事接口的统称。WSDL提供“能办的事的文档说明”&#xff1a;对要提供的服务的一种描述格式。我想帮你的忙&#xff0c;但是我要告诉你我都能干什么&#xff0c;以及干这些事情需要的…

java uuid静态方法_Java UUID nameUUIDFromBytes()方法及示例

java uuid静态方法UUID类名UUIDFromBytes()方法 (UUID Class nameUUIDFromBytes() method) nameUUIDFromBytes() method is available in java.util package. java.util包中提供了nameUUIDFromBytes()方法 。 nameUUIDFromBytes() method is used to get a UUID constructed fr…

清空 linux 服务器,Linux服务器清理

Why?废话不多说直接来图&#xff0c;可以看出磁盘已经快要满了未清之前What?可以看出mnt文件夹占用的最大&#xff0c;然后进入mnt目录里通过命令,根据文件大小对该路径下文件排序du -h --max-depth1我们服务器出现磁盘快满了的原因是因为&#xff0c;服务器部署了多个tomcat…

Git中的AutoCRLF与SafeCRLF换行符问题

2019独角兽企业重金招聘Python工程师标准>>> 原文&#xff1a;http://www.cnblogs.com/flying_bat/archive/2013/09/16/3324769.html 最近在使用GitHub&#xff0c;发现不时没有修改过的文件要提交&#xff0c;对比发现文件全部修改&#xff0c;但找不到不一样的地方…

stringwriter_Java StringWriter getBuffer()方法与示例

stringwriterStringWriter类的getBuffer()方法 (StringWriter Class getBuffer() method) getBuffer() method is available in java.io package. getBuffer()方法在java.io包中可用。 getBuffer() method is used to get the StringBuffer that holds the present buffer valu…

linux 下邮件服务器,Linux 下搭建Postfix邮件服务器

Linux 下搭建Postfix邮件服务器详解&#xff1a;1、首先关闭sendmail服务service sendmail stop2、chkconfig sendmail off(关闭开机自启动)3、修改DNS正解文件&#xff0c;使DNS能够解析邮箱服务添加下面两行mail.zhubf.com. IN A 172.17.17.2zhubf.com. IN M…

Java PipedInputStream close()方法与示例

PipedInputStream类close()方法 (PipedInputStream Class close() method) close() method is available in java.io package. close()方法在java.io包中可用。 close() method is used to close this PipedInputStream and free all system resources linked with this stream…

Coreseek Windows下安装调试

由于项目需要全文检索&#xff0c;后面就去网上查了下资料&#xff0c;找到了Sphinx【中文是狮身人面像】这个全文检索引擎&#xff0c;听说挺好用的&#xff0c;不过没有中文分词。后面又去找了一下&#xff0c;找到了Coreseek&#xff0c;一款中文全文检索/搜索软件。 一、Sp…

linux sudo命令全称,linux sudo命令的概念与使用

1.sudo介绍本文引用地址&#xff1a;http://www.eepw.com.cn/article/201610/305498.htmsudo是linux下常用的允许普通用户使用超级用户权限的工具&#xff0c;允许系统管理员让普通用户执行一些或者全部的root命令&#xff0c;如halt&#xff0c;reboot&#xff0c;su等等。这样…

java 方法 示例_Java语言环境getISOCountries()方法与示例

java 方法 示例区域设置类getISOCountries()方法 (Locale Class getISOCountries() method) getISOCountries() method is available in java.util package. getISOCountries()方法在java.util包中可用。 getISOCountries() method is used to return an array of string that …

android shape.xml 属性详解

转载源:http://blog.csdn.net/harvic880925/article/details/41850723 一、简单使用 刚开始&#xff0c;就先不讲一堆标签的意义及用法&#xff0c;先简单看看shape标签怎么用。 1、新建shape文件 首先在res/drawable文件夹下&#xff0c;新建一个文件&#xff0c;命名为&#…