当前位置: 首页 > wzjs >正文

xx企业网站建设方案书苏州公司网站建设报价

xx企业网站建设方案书,苏州公司网站建设报价,用哪个平台做网站好,网页设计找什么工作前言 在阅读Netty源码的过程中,我越来越相信一句话:“Netty的源码非常好,质量极高,是Java中质量最高的开源项目之一”。如果认真研究,会有一种遍地黄金的感觉。 本篇文件我将记录一下鄙人在Promise的实现类DefaultPr…

前言

在阅读Netty源码的过程中,我越来越相信一句话:“Netty的源码非常好,质量极高,是Java中质量最高的开源项目之一”。如果认真研究,会有一种遍地黄金的感觉。

本篇文件我将记录一下鄙人在Promise的实现类DefaultPromise中发现的一块黄金:即用来存储监听器的集合的设计。

问题引入

接上文《Netty源码解析之异步处理(一):Promise系列的源码与实现原理》,在使用Promise时,可以往Promise里面加多个监听器。那么在Promise中改用什么集合来保存已经添加的监听器呢?
我认为大部分程序员都会使用一个Set或List等集合来存储,Netty则认为这些统统不合适,使用了自定义的DefaultFutureListeners集合来存储。

Promise中的集合设计

奇怪的listeners属性

在DefaultPromise源码中,用来存储监听器的属性是一个Object类型的listeners。乍看会觉得很奇怪,因为Promise中的监听器可能不止一个,用一个非集合的listeners如何存储?

DefaultPromise源码中的listeners

//用来存储添加到Promise中的监听器
private Object listeners;

单个监听器添加部分的源码

为了解答上面的疑问,需要看下DefaultPromise中添加单个监听器部分的源码,位于addListener0(GenericFutureListener listener) 方法中。

    private void addListener0(GenericFutureListener<? extends Future<? super V>> listener) {//当listeners == null时,表示是第一次添加监听器if (listeners == null) {listeners = listener;//等到第三次添加时,listeners已经是DefaultFutureListeners对象//因此走了这一步} else if (listeners instanceof DefaultFutureListeners) {((DefaultFutureListeners) listeners).add(listener);//当listeners != null,表示已经不是第一次添加//如果是第二次添加的话,listeners此时是一个监听器GenericFutureListener的实例,//因此,第二次添加的话,走这一步,创建DefaultFutureListeners实例赋值给listeners} else {listeners = new DefaultFutureListeners((GenericFutureListener<?>) listeners, listener);}}

从上面的源码中,我们可以看出,添加单个监听器分为三种方式:

1、第一次添加监听器时,直接把监听器,即GenericFutureListener类型的实例赋值给DefaultPromise中用来存储监听器的listeners属性。

2、第二次添加监听器时,创建了DefaultFutureListeners集合的对象,并且将两次添加的监听器作为参数传递。
然后,我们进入DefaultFutureListeners的构造方法。

    DefaultFutureListeners(GenericFutureListener<? extends Future<?>> first, GenericFutureListener<? extends Future<?>> second) {//创建一个长度为2的数组listeners = new GenericFutureListener[2];//将第一次和第二次添加的两个监听器存入数组中listeners[0] = first;listeners[1] = second;//数组长度为2size = 2;//如果添加的监听器是进度监听器,progressiveSize自增1if (first instanceof GenericProgressiveFutureListener) {progressiveSize ++;}if (second instanceof GenericProgressiveFutureListener) {progressiveSize ++;}}

可以发现,在DefaultFutureListeners的构造方法中,创建一个长度为2的数组listeners,然后将第一次和第二次添加的两个监听器存入数组中。这时候,可以说两个监听器已经存储在DefaultFutureListeners集合中。

3、等到第三次或第三次以后添加时,调用DefaultFutureListeners的add方法将监听器存入集合。
在DefaultFutureListeners的add方法中,进行了检查数组长度和监听器插入数组等操作,没什么特别的。

    public void add(GenericFutureListener<? extends Future<?>> l) {GenericFutureListener<? extends Future<?>>[] listeners = this.listeners;//获取当前集合中元素的数量final int size = this.size;//如果当前集合中元素的数量等于数组长度//说明本次添加时,数组长度就不足,因此数组需要扩容if (size == listeners.length) {//数组扩容,先用左移位将新数组长度设为原数组长度的两倍//然后使用数组拷贝的方式得到新数组this.listeners = listeners = Arrays.copyOf(listeners, size << 1);}//将监听器插入数组中listeners[size] = l;//集合中元素数量增加1this.size = size + 1;//如果本次添加的是进度监听器,progressiveSize也自增1if (l instanceof GenericProgressiveFutureListener) {progressiveSize ++;}}

Promise中集合设计的思考

为什么要这么设计?

刚开始我觉得非常奇怪,
1、为什么不直接把DefaultPromise源码中的listeners属性设为一个ArrayList类型的集合,而是要兜了一圈才用集合?
2、为什么DefaultFutureListeners创建后,其内部的数组长度只有2?多给点初始长度不是能避免数组扩容吗?

后来我在不断地阅读Netty源码时发现,在几乎全部的Promise实际使用场景中,添加的监听器数量很少,同一个Promise在大部分情况下只用了1个监听器,很少数情况下用了2个监听器,用到3个监听器的情况从未见过。

基于这种实际情况,如果刚开始就创建一个集合,甚至给集合中的数组分配一定的初始长度的话,在性能和存储空间上都是浪费!因为在大部分场景下一个Promise只包含1个监听器,所以直接把这一个监听器赋值给listeners属性是最好的选择。如果遇到了极少数的需要包含2个监听器的情况,那也只创建一个长度为2的数组来保存,因为监听器再多的情况几乎没有,这样避免空间浪费。

这种设计和编码方式叫做“启发式编程”。

使用栈可不可以?

我也想过Promise的监听器使用栈这种数据结构来存储是否可以,这样的话我们只要在监听器GenericFutureListener中定义一个next属性,用来指向下一个监听器即可,编码更加简洁和方便。

我认为可以,但是性能不如数组。因为在Promise的源码中,存储的监听器最多的使用场景就是遍历全部然后触发。因为数组在内存中是连续的,正好可以利用计算机的局部性原理,能让CPU缓存把本身就很小的数组全部读入,进而能以最快的速度进行遍历。而栈使用的是链表结构,链表的节点是分散在堆空间里面的,很难使用到CPU缓存。

数组与CPU缓存的详细关联请参考:https://www.cnblogs.com/ajuanabc/archive/2009/03/28/2462628.html


文章转载自:

http://zVDL3kft.byzpL.cn
http://C2MeR2Bz.byzpL.cn
http://ZvAgQL0P.byzpL.cn
http://zenFPmy6.byzpL.cn
http://NYx7XMX0.byzpL.cn
http://A1YXv45w.byzpL.cn
http://AuDVuOWm.byzpL.cn
http://JAoH2esS.byzpL.cn
http://qmZ3qsEv.byzpL.cn
http://uo2XgJZf.byzpL.cn
http://TMlFAZ1a.byzpL.cn
http://5djUcGUh.byzpL.cn
http://IdpnB9hV.byzpL.cn
http://SDzucTTM.byzpL.cn
http://UK8vEyy5.byzpL.cn
http://nknvew9z.byzpL.cn
http://0yTWVeMd.byzpL.cn
http://E9c6SzIh.byzpL.cn
http://ZqL0WniI.byzpL.cn
http://4j1H92jA.byzpL.cn
http://EVzFGrza.byzpL.cn
http://Frrd9reg.byzpL.cn
http://tIfl48vN.byzpL.cn
http://LwGM26YX.byzpL.cn
http://EtYKC8eG.byzpL.cn
http://cBYpPB6w.byzpL.cn
http://ckllChGN.byzpL.cn
http://HSef0T0C.byzpL.cn
http://wOFcMkn4.byzpL.cn
http://xsdsULoI.byzpL.cn
http://www.dtcms.com/wzjs/763730.html

相关文章:

  • 网站建设营销的技巧跑胡子网站开发
  • 西安网站开发高端网站开发手机网站用什么软件做的好
  • 网站开发创业西安市长安区规划建设局网站
  • 自己有网站怎么做app建立视频网站
  • 文本分析网站设计logo网站免费下载
  • paypal客户端网站建设评价想做电商怎么注册
  • 下载整个网站的软件有哪些网站是可以接单做任务的
  • 网站的专区怎么建设模板规格尺寸
  • 什么网站自己做名片好WordPress来必力
  • 朵以服饰 网站建设全国小微企业名录查询
  • 比较有名的个人网站网站里做任务
  • 湖州公司做网站怎么管理网站的内容
  • 温州网站建设选择乐云seo摄影网站建设任务书
  • 网站被黑能查到是谁做的吗做网站构建
  • 建设维护网站 未签订合同做网站要多少
  • 专业网站建设技术注册进出口贸易公司条件
  • 退役军人事务部网站建设wordpress 首页显示产品
  • 浙江省建设监理管理协会网站外贸英才网
  • 服装时尚网站做三国的网站
  • 网站建设 维护购销合同承德网站建设作用
  • 网站固定通栏代码汉网网站建设
  • 宁夏网站建设一条龙可以做四级的网站
  • 网站设计教科书wordpress电脑微信登陆不了
  • 那些网站可做国外零售厦门市住房和城乡建设局网站
  • 网站备案 厦门郑州+高端网站建设
  • asp网站咋做重庆建设工程信息网怎么录入备案
  • 定制网站建设宝安西乡wordpress国内备份神器
  • seo流量排名门户seo在网站制作
  • 网站有哪些风格深圳网站制作要多少钱
  • 为什么要建立企业网站个人手机网站开发