java的8年来工作汇总

Posted 幕风落雨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java的8年来工作汇总相关的知识,希望对你有一定的参考价值。

目录

前言

一、大学阶段

二、毕业后八年

1.基础前三年

2.门槛第五年

3.进阶第七年

3.对未来的规划or计划

总结





前言

         今年已经是我工作第八年,感觉自己算是不上不下,也谈不上多优秀,也不是多么的差,总感觉自己还是有足够的干劲,虽然已经是30的人了。总的来说今天翻看大学的日记,记录了学习过程,感情生活等等。突然想起写一篇博客对自己的工作期间总结。自己也是啰啰嗦嗦,博客也是最近才开始想要留下一些自己存在过得证明,也方便我未来回顾一下自己的人生往事。好久没有写有点生疏,后续想要陆陆续续补充一些开发方面的知识,技术相关管理相关的知识。




一、大学阶段

        我的大学是一个普普通通的二本,去年看新闻虽然现在已经升到一本了,值的高兴一下。回想大学期间学习上面真的谈不上有多大理想多大报复都是随波逐流的方式度过了大学生活;

        第一年,担任班长,了解了一下计算机的基本原理,C语言跟着大学老师教学走;充满了干劲,但是选择了我最不喜欢连QQ,邮箱,word,拼音打字贼慢,还没有 买电脑;拖拖的山沟沟里面出来的怎么用都不会;当年的同寝室的同学加基友帮忙申请了一个qq账号,名字也是用到了现在一直没有 更换。当班长期间最大的记忆便是学校要提交excel统计班上情况需要发送邮件;我一脸的懵逼,当时下定决心在大一期间每天下完晚自习去学校的机房里面学习word,excel,还有上课学习的c语言(当时学校机房电脑有安装好的软件直接开发就行),qq和以前的同学联系练习两个小时(当时机房一小时只要1元);

        小结:无人指导,大一的迷茫,无路可走的感觉;那么现将基础知识先学习消化并且不断地尝试学习更加深入的理论知识,为后续的学习高级语言铺路。在学习专业知识当中找到自己的突破点。希望对于普通的不是天才的我们有一点作用,现在发现基础知识到了现在工作八年后的我仍然很有作用,用于排查工作遇到的各种疑难杂症,特别是疑难杂症的入手就是这些大一学习的额基础知识;感谢大一的自己不贪玩。

        第二年,第二年买了笔记本,开始非常兴奋开始玩游戏,看网络小说。当时可以说沉迷其中无法自拔,第一学期就这样度过了。来到下学期在家里面看到父母不断增加的皱纹,冬天手上的裂纹;让深刻的反省了自身,我从山沟沟里出来,父母背的一屁股债让我无比的自责,虽然在大学期间有勤工俭学,但是也就是周六日学校看看机房就行顺便学习简单的计算机使用但是远远不够。第二学期开始早上六点起来去早读英语,为了考4级证书(自豪的是拿了4级证书,高中平均分60分不到的人);白天上完课,周一到周五晚上在图书馆看java的书到9:00,回宿舍敲代码到11:00然后睡觉,周六日还是会玩游戏游戏的时间非常少;(其实也不知道学习什么方便就看到java学习的人数最多;可能后续不会被抛弃,至少十年内没有任何问题。)

        小结:迷茫当中选择游戏来释放自己的精力,迷茫当中被当头一棒;虽然仍然很迷茫,但是至少自己开始尝试找学习的知识。现在想来那时候应该要多去招聘网站上面看java需要学习的知识,需要了解的技术,只有实际需要才是最值得学习。没有主动和已工作的朋友咨询意见,导致在学习过程当中自己仍然很迷茫;不管那个行业应该都去看看实际的需求,这样的学习才是有目标,如果是准备考研的可以先跟各个老师询问咨询相关的学习内容。不要盲目发力,需要有目标,计划,过程可执行,最终达成的成果产出才行。毅力和方法非常关键,做事情切不可半途而废需要持续的去做不断地完成既定的小目标,增强自我的认可,增强自信心。(由于4级证书这个事情让我自己觉得自己不是废物,找到自信没有完成不了的事情;只要执行力和方法对没啥困难能难倒我。)

        第三年,第三年开始有点迷茫自学期间由于没有进入过工作室,不知道java真的怎么使用,觉得自己对java的内容都充分的了解简单的项目搭建和开发也没啥大问题(当时不知道天高地厚)。开始逐步的喜欢打篮球,第三年一年的时间傍晚都会打篮球1小时,然后才会去学习java,c++,html前端,javascript和敲一些简单的开发代码,当时觉得前端内容挺有呈现感觉就自学了一学期的时间。大三下学期的实习让自己找到了java更近一步的方向,了解到简单的框架知识需要学习。在暑假实习期间开始自学框架。虽然开始自学但是仍然很吃力,大部分时间都放在了寻找学习资料,整理学习资料方面。

        小结:有点小目标,但是仍然不明确未来的出路。得过且过的日子,没有太多的压力和动力;安逸的日子缺乏危机感,对自己盲目的自信且没有找对方向和目标。当学习工作遇到瓶颈的时候需要找到正确的入门口径,当自己无法确定是否正确的时候需要寻找外部事物刺激自己寻找到正确的方向。只有目标方向正确尝试去做未来才有可能,如果都去尝试最终可能都完成不了,最终都做的一般般。

        第四年,危机感充足开始购买框架书籍学习大量的框架知识,通过大量的填鸭式学习spring框架,对框架有了简单的理解认知,然而知识停留在最基本的使用。没有跟进一步但是应对基本开发应该还是可以了。无任何的项目实战经验而且基础知识也不牢靠。第二学期开始各种找工作各种面试,各种碰壁经过二十几次还是三十几次的碰壁终于静下心来两周将spring框架所有的知识都学习了一遍,除了吃饭和睡觉的七小时时间其他时间都在学习和代码。之后再去面试立马面试上了,虽然工资很低但是很满足,我相信自己未来可期;也制定了后续五年的计划。开始有条不紊的执行自己的计划。

        小结:基础知识不牢靠,平常不积累学习知识。未来有机会摆在眼前也只能干瞪眼。如果知识积累确实不足的情况下,希望你也不要放弃通过不服输的精神仍然可以追赶上去;我经历过过程非常痛苦和我之前有准备的同学比我真的在追赶的过程当中付出的太多太多。在大学四年当中自己未曾放弃自己,未曾放弃寻找自己的目标;翻看大四的日记里面的五年计划,我都已经实现了。大学四年的迷茫让我懂得了目标和计划的重要。也让我积累了一些自己的做事方式,任何时候都不要自暴自弃,任何时候都不要放弃自己,任何时候都要相信自己能行。希望一直留给有准备的人,所有人的成功都不是运气,运气只是成功的人的一种谦虚的表达。

二、毕业后八年




1.基础前三年

        毕业后的我一直按照大四的时候的规划,打算前面三年积累学习的基础知识的灵活运用。先解决自己的温饱问题,能够养活自己;不管过得多么痛苦或者多么的难受都按照既定目标前行;

        2013年毕业第一年工资两千多一个月,刚好养活自己在一线城市能够勉强存活。在毕业第一年基本上保持了下班回家必定学习两个小时的ssh框架知识和java web框架知识的学习,也有偏离java的资料学习过安卓开发,也学习过js的一些前端框架现在已经忘记了什么框架当时学习挺有兴趣。基本上前后端都要学习,工作当中使用的是ssm框架学习起来可以实际上面使用,第一年大部分的时间是系统运维类的工作功能需求开发比较少,没有大的项目都是在现有框架当中做基础开发和运维。通过上班下班的时间积累知识储备非常重要,也让我明白了各种平台的搜索,各种资源如何快速搜索到。这个过程积累了查找知识过滤知识的重要性。

        第一年沉淀了部分的基础知识,由于个人发展和需求开始了第二年的到了第二家公司,第二家公司就我一个开发java后端,在这家公司基本上所有的sql优化,后端优化,前端开发都由我一人包办,虽然当时不懂什么是架构,什么是需要调整;当时基本上把第一年学习的内容在第二家公司用了差不都,而且第二家公司的框架很奇特也很新颖前端界面可生成,可配置;性能瓶颈很大,但是简单开发功能特别轻松。在这家公司主要是将各个数据库都摸了一遍,由orcale迁移数据到sqlserver然后再由sqlserver迁移到mysql。在这个迁移的过程当中学习了挺多东西也使用到了各种工具和框架知识,这个阶段我开始觉得有点点自己的知识积累。由于一个人的开发没有对比所以当时工资待遇各方面都是非常低也就4千不到吧。那时候我的感觉就是只要进入这个行业一切都可以通过自学得到更多。无指导就需要更多的时间自我思考问题,发现问题和解决问题。在这个过程当中不断地积累经验。

        第三年进入到第三家公司算是真正的互联网公司了;虽然是互联网里面的小公司,但是开发人员也有将近40多人,在这里面我开始有了对比有了自我的定位。在这里我才真正的找到了我在行业内的情况,也随着我前两年的知识积累;在这家公司的工资待遇也是两个月涨薪幅度都非常大,可能本身我进去的时候基数就很小。在这个过程当中我开始逐步的建立了自信,开始将我在第一家公司的时候学习的基础只是运用;在第二家公司自我思考,发现问题,解决问题的思路得以贯通。虽然在这家公司加班非常非常严重,但是开发经验的积累,熟练的使用所学知识在这一年让我特别的开心和自我的肯定。建立了我对我行业的乐观态度,也让我开始逐步的有一点点膨胀。学习知识没有第一二年那么必须两个小时学习的干劲,也进入到了一个瓶颈;虽然进入瓶颈但是没有想要去突破,也没有时间去思考如何突破。在这阶段认清自己的实际情况,认清现实,肯定自己的付出。前期的积累在后面是会有回报的而且力度非常大。




2.门槛第五年

        出于突破的瓶颈打破自身的束缚,在第三家公司离职之后进入到第四家公司也是我至今都觉得这家公司让我真正体会到IT从业者的细分不再是小作坊的方式,而是职能的细分,工作的细分。也在这公司让我看到了整个行业的细分情况组织架构和人员配比。虽然整个部门也就三百多个人,但是细分了很多产品;产品里面又分测试,开发,需求,前端,后端,移动端,大数据,基础运维基本上都有配比。跨部门之间的协作开发都是让我以前没有遇到过的。我算是一个野路子出身的程序员,纯粹的野蛮生长完全靠自己摸索的方式一路走过来。

        突破瓶颈,我觉得我非常幸运,也非常的感谢当时的老大;让我可以在他的指导下一步步的学习到新的技术,新的突破点;能够在技术和管理上面都能够有很大的进步和突破,发现工作当中可以通过各种途径去学习到新的技术,新的理念并且给与时间去尝试。在2016年微服务才刚刚火起来的时候我所在的项目组已经应用到项目当中,我很庆幸能够加入这个团队;当时将旧的项目框架体系整改成微服务架构全称参与其中,并且担任核心开发人员。在里面使用到了dubbo,后期也使用到了spring cloud框架。在一步步的探索和实践大当中找到了自己的路,在这个项目当中我负责其中一个子项目,并且也带了两位同事一起开发。在开发过程当中的任务分配,项目计划进度等跟进。让我一个作为普通程序员的有机会接触到不一样的事情;后面我定位为项目经理和技术经理的角色是我后期的目标也找到了方向。(前面三年虽然有了解过但是作为程序员基础都不牢靠,职业在细分也没有一个明确努力的方向,在这么多不确定的情况下努力。不断前进)

        项目管理方面也在这家公司的时候任务安排都很合理,我有足够多的时间去学习新知识;在第五年也考了PMP的项目管理资格证;技术方面,大部分学习的新知识都能够上到生产环境;其中有一些新的技术不够成熟也不能上线生产环境,只能自己做一个项目单独跑跑。特别喜欢的事在公司里面每周五都有技术分享会,不管是前端,后端,大数据,运维,甚至是网络方面的分享。都能够让我耳目一新,感觉自己的知识的贫乏和之前的无知;在这里我觉得技术得到了补充,也静下心来审视自己给自己当头一棒活到老学到老。

        第五年的时候我仍然是一个开发组长,也学习了各种不同的技术可能基于表面没有深入理解,在第五年的时候开始逐步的深入理解其中的原理和思想;现在想来第五年我才真正的进入到一个门槛,才算真正的理解了IT行业,才算真正的了解了自己的位置。想要更近一步则需要有机会也需要有实力能够抗住压力。在这家公司我可能作为一个研究类的开发,但是与我的目标项目经理和技术经理有点差异。或许当时我太偏执了其实可以走架构师方向;但是没有回头路我自己选择了技术经理就必须一路走下去。也让我开始寻找发展或者说展现自己的舞台(对于我来说我觉得将自己的所学运用到现实生活当中是一件非常有成就感的事情)。我内心其实非常渴望能够将自身所学融汇贯通,能够将学习到的点点滴滴真真切切的应用起来。或许当时的心境我在第五年年底离开了这家公司。

3.进阶第七年

     第六年到了新的公司,有了新的同事,公司也足够大;也有足够的项目和实战。再来到这家公司的时候;我和我的导师根据新的微服务框架拆分后端应用,拆分前端应用做单独部署;系统的各个项目子模块发版互不影响。同时代码管理奖svn转换成git的管理方式,针对git的代码规范合并规范的制定。这一年不单单带了一个80w+的子项目做技术负责人练练手。同时管理了公共服务内容。在这里我每天忙碌差不多是806的架势。工作时间超过12小时,差不多6个月的时间保持这种高强度工作,但是充分的将我在上加公司无法时间的项目实践了一遍。(在这个过程当中脑海里面其实出现过无数次的离职想法,无法正确的把控时间,无法合理的分配时间,无法做到有效的沟通等问题。疲于实现交付和解决公共问题。)我仍然停留在类似开发组长的角色。除了完成需求评审,概要设计,详细设计,开发计划指定和跟进等。缺少了对项目立项,里程碑交付,成本的控制等是在项目当中的必备的东西。

     第七年年初将项目的好的地方和遇到错误的问题,以及自己的解决方法有问题。在这独自开始带领240w+项目的技术负责人(后续四次大的迭代版本差不多140w)。在这次让我懂得了如何合理拆分任务,合理的拆分功能分配功能,能够合理的给项目遇到的问题提供技术解决方案;沟通能力直线上升,能够根据同事反馈信息快速理解对方想要表达的意思。在这一年让我懂得了成本的控制,如何高效的带领团队开发。在本次项目当中让我接触到了很多突发情况:如用户量增加一百倍,由日活100到日活10000的用户量。在突发情况如何解决高并发;如何在有限的资源固定的时间内解决问题。方案制定该如何避免产生二次问题。遇到任何事情第一保持头脑清醒,按照思路根据问题点,分析问题产生原因。当前问题解决之后,同类型的问题一并排期进入到第二次的版本迭代。问题分析途径,数据库sql-》各种监控链路-》各种能够过去到的请求响应时间-》各种业务场景覆盖。在该过程当中不断的深入java底层,框架的底层知识积累。

       第八年在沉淀前一年的积累,不断地总结学习的专业知识点,项目管理的方法,问题分析方法。在这个过程当中思维的转变非常巨大,可以说真正的摆脱需要别人分配工作给我我去执行。而是成为我自己给自己安排工作,自己给自己不断地找事情做。提前发现项目的问题,提前想到下一步的项目优化点。提前做好预防下一步会出现的问题,按部就班一年内不断迭代完善项目。在这个过程当中也会参与其他项目的架构和设计的评审,对其他项目提出自己的方案和意见,同时开始整合制定项目管理规范,开发规范,技术文档积累,监控预警的积累。逐步开始有前瞻性一般评估一两年需要做的事情。

4.对未来的规划or计划

         技术方面:1、对未来的规划或许在我眼里技术的不断创新和学习是非常重要。(技术的必须要有深厚的功底,才能做好一个资深技术架构师)目前技术积累还不够深度不够,仅仅掌握了一套性能优化,问题排查的方法论;对于技术底层的实现思想,各种框架的不同场景应用还不是很清晰。面和点都不够远远没达到我的预期。2、下一步三年内学习的新技术不能少于五种,拓展一下自己的知识面。

        对于项目沟通等方面1、重点提升表达能力,说话简短精要。2、增强主观能动性,工作中做好前瞻性问题分析。3、对未来三到五年内的方向分析,做好物联网的学习知识储备(产品类的知识积累)





总结

       作为一个普通的程序开发者,我只能相信自己能够在35岁到来的时候不被淘汰,能够安全度过35岁危机。目前暂时感觉IT行业的发展对架构师的渴求,对技术经理的渴求仍然是非常巨大的缺口。从目前我去招聘面试的情况来分析,面试者的水平远远还没有达到我目前所在公司的要求水平。公司缺口目前也是非常大。希望能够通过充实自己五年内完成我自己的边界突破。

      任何事情都有解决方法,任何简单问题的表象下面都会埋藏一个巨大的雷。低头做事,偶尔抬头看路。如果你我都是打工人,请切记时间宝贵低头做事的同时切勿忘记抬头看路。希望最后你我都是能够成为引入人,而不是寻路人。

Java集合详解10:ConcurrentHashmap面试题汇总,最近找工作老是被问!

ConcurrentHashMap篇

HashMap 和 ConcurrentHashMap 的区别

  1. ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的synchronized锁的粒度更精细了一些,并发性能更好,而HashMap没有锁机制,不是线程安全的。(JDK1.8之后ConcurrentHashMap启用了一种全新的方式实现,利用CAS算法。)
  2. HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。

ConcurrentHashMap 和 Hashtable 的区别?

ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。

  • 底层数据结构: JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;
  • 实现线程安全的方式(重要): ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。(默认分配16个Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;② Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。

两者的对比图

HashTable:

img

JDK1.7的ConcurrentHashMap:

img

JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点):

img

答:ConcurrentHashMap 结合了 HashMap 和 HashTable 二者的优势。HashMap 没有考虑同步,HashTable 考虑了同步的问题。但是 HashTable 在每次同步执行时都要锁住整个结构。 ConcurrentHashMap 锁的方式是稍微细粒度的。

ConcurrentHashMap 底层具体实现知道吗?实现原理是什么?

JDK1.7

首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。

在JDK1.7中,ConcurrentHashMap采用Segment + HashEntry的方式进行实现,结构如下:

一个 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁。

img

  1. 该类包含两个静态内部类 HashEntry 和 Segment ;前者用来封装映射表的键值对,后者用来充当锁的角色;
  2. Segment 是一种可重入的锁 ReentrantLock,每个 Segment 守护一个HashEntry 数组里得元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁。

JDK1.8

JDK1.8中,放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率又提升N倍。

结构如下:

img

附加源码,有需要的可以看看

插入元素过程(建议去看看源码):

如果相应位置的Node还没有初始化,则调用CAS插入相应的数据;

 
  1. else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {

  2. if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null)))

  3. break; // no lock when adding to empty bin

  4. }

如果相应位置的Node不为空,且当前该节点不处于移动状态,则对该节点加synchronized锁,如果该节点的hash不小于0,则遍历链表更新节点或插入新节点;

 
  1. if (fh >= 0) {

  2. binCount = 1;

  3. for (Node<K,V> e = f;; ++binCount) {

  4. K ek;

  5. if (e.hash == hash &&

  6. ((ek = e.key) == key ||

  7. (ek != null && key.equals(ek)))) {

  8. oldVal = e.val;

  9. if (!onlyIfAbsent)

  10. e.val = value;

  11. break;

  12. }

  13. Node<K,V> pred = e;

  14. if ((e = e.next) == null) {

  15. pred.next = new Node<K,V>(hash, key, value, null);

  16. break;

  17. }

  18. }

  19. }

  1. 如果该节点是TreeBin类型的节点,说明是红黑树结构,则通过putTreeVal方法往红黑树中插入节点;如果binCount不为0,说明put操作对数据产生了影响,如果当前链表的个数达到8个,则通过treeifyBin方法转化为红黑树,如果oldVal不为空,说明是一次更新操作,没有对元素个数产生影响,则直接返回旧值;
  2. 如果插入的是一个新节点,则执行addCount()方法尝试更新元素个数baseCount;

15.Java中的另一个线程安全的与HashMap极其类似的类是什么?同样是线程安全,它与HashTable在线程同步上有什么不同?

ConcurrentHashMap类(是Java并发包java.util.concurrent中提供的一个线程安全且高效的HashMap实现)。
HashTable是使用synchronize关键字加锁的原理(就是对对象加锁);
而针对ConcurrentHashMap,在JDK1.7中采用分段锁的方式;JDK1.8中直接采用了CAS(无锁算法)+synchronized

16.HashMap&ConcurrentHashMap的区别?

除了加锁,原理上无太大区别。另外,HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。

17.为什么ConcurrentHashMap比HashTable效率要高?

HashTable使用一把锁(锁住整个链表结构)处理并发问题,多个线程竞争一把锁,容易阻塞;
ConcurrentHashMap

  • JDK1.7中使用分段锁(ReentrantLock+Segment+HashEntry),相当于把一个HashMap分成多个段,每段分配一把锁,这样支持多线程访问。锁粒度:基于Segment,包含多个HashEntry

  • JDK1.8中使用CAS+synchronized+Node+红黑树。锁粒度:Node(首结点)(实现Map.Entry<K,V>)。锁粒度降低了。

18.针对ConcurrentHashMap锁机制具体分析(JDK1.7VSJDK1.8)?

JDK1.7中,采用分段锁的机制,实现并发的更新操作,底层采用数组+链表的存储结构,包括两个核心静态内部类SegmentHashEntry

  • ①、Segment继承ReentrantLock(重入锁)用来充当锁的角色,每个Segment对象守护每个散列映射表的若干个桶;

  • ②、HashEntry用来封装映射表的键-值对;

  • ③、每个桶是由若干个HashEntry对象链接起来的链表;

JDK1.8中,采用Node+CAS+Synchronized来保证并发安全。取消类Segment,直接用table数组存储键值对;当HashEntry对象组成的链表长度超过TREEIFY_THRESHOLD时,链表转换为红黑树,提升性能。底层变更为数组+链表+红黑树。

19.ConcurrentHashMap在JDK1.8中,为什么要使用内置锁synchronized来代替重入锁ReentrantLock?

  • ①、粒度降低了;

  • ②、JVM开发团队没有放弃synchronized,而且基于JVMsynchronized优化空间更大,更加自然。

  • ③、在大量的数据操作下,对于JVM的内存压力,基于APIReentrantLock会开销更多的内存。

20.ConcurrentHashMap简单介绍?

  • ①、重要的常量:

    • private transient volatile intsizeCtl;

    • 当为负数时,-1表示正在初始化,-N表示N-1个线程正在进行扩容;

    • 当为0时,表示table还没有初始化;

    • 当为其他正数时,表示初始化或者下一次进行扩容的大小。

  • ②、数据结构:

    • Node是存储结构的基本单元,继承HashMap中的Entry,用于存储数据;

    • TreeNode继承Node,但是数据结构换成了二叉树结构,是红黑树的存储结构,用于红黑树中存储数据;

    • TreeBin是封装TreeNode的容器,提供转换红黑树的一些条件和锁的控制。

  • ③、存储对象时(put()方法):

    • 1.如果没有初始化,就调用initTable()方法来进行初始化;

    • 2.如果没有hash冲突就直接CAS无锁插入;

    • 3.如果需要扩容,就先进行扩容;

    • 4.如果存在hash冲突,就加锁来保证线程安全,两种情况:一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入;

    • 5.如果该链表的数量大于阀值8,就要先转换成红黑树的结构,break再一次进入循环

    • 6.如果添加成功就调用addCount()方法统计size,并且检查是否需要扩容。

  • ④、扩容方法transfer(): 默认容量为16,扩容时,容量变为原来的两倍。
    helpTransfer(): 调用多个工作线程一起帮助进行扩容,这样的效率就会更高。

  • ⑤、获取对象时(get()方法):

    • 1.计算hash值,定位到该table索引位置,如果是首结点符合就返回;

    • 2.如果遇到扩容时,会调用标记正在扩容结点ForwardingNode.find()方法,查找该结点,匹配就返回;

    • 3.以上都不符合的话,就往下遍历结点,匹配就返回,否则最后就返回null

21.ConcurrentHashMap的并发度是什么?

程序运行时能够同时更新ConccurentHashMap且不产生锁竞争的最大线程数。默认为16,且可以在构造函数中设置。当用户设置并发度时,ConcurrentHashMap会使用大于等于该值的最小2幂指数作为实际并发度(假如用户设置并发度为17,实际并发度则为32)

微信公众号【程序员书单】

一个为程序员推荐好书的公众号。每周为你pick精品书单,优质学习资源和工具软件。关注前沿技术与行业资讯,更关注你的自我提升。人生苦短,要把时间浪费在美好的事物上~

回复“book”即可领取java后端学习必备20+本电子书。更多电子书下载,请移步至程序员书单官网:coderbooklist.com

微信公众号【Java技术江湖】

一位阿里 Java 工程师的技术小站,专注于 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!

关注公众号后回复“PDF”即可领取200+页的《Java工程师面试指南》强烈推荐,几乎涵盖所有Java工程师必知必会的知识点。

以上是关于java的8年来工作汇总的主要内容,如果未能解决你的问题,请参考以下文章

Java 大后端各种架构图汇总(建议收藏!!)

Java 后端到底是在做啥?

源码解析:Java春招实习面试经验汇总真的太香了!

JAVA后端第三阶段汇总(更新中~~)

Java开发之上帝之眼系列教程前言和章节目录汇总

三年java开发-1