代码review
写这篇文章的原因是昨天在工作期间完成业务要求的时候,根据组长的要求写了自己的代码,结果在之后组长review的时候,发现了很多不足的地方,所以写这篇博客进行记录。
话不多说,先上原始代码。
public class DocValuesWarmUpListener extends AbstractSolrEventListener{
private static final Logger logger = LoggerFactory.getLogger(DocValuesWarmUpListener.class);
private List<String> fields;
public DocValuesWarmUpListener(SolrCore core) {
super(core);
}
@Override
public void init(NamedList args) {
super.init(args);
fields = new ArrayList<>();
NamedList o;
if(args != null) {
o = (NamedList) args.get("fields");
if(o!=null && o instanceof NamedList) {
for (int i = 0; i < o.size(); i++) {
fields.add((String) o.getVal(i));
}
}
}
}
@Override
public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
long start = System.currentTimeMillis();
ExecutorService executorService = Executors.newFixedThreadPool(fields.size());
try {
//排序所需要用到的字段,用一个线程池多线程预热
for(int i=0;i<fields.size();i++) {
executorService.execute(new WarmUpDocValueThread(fields.get(i),newSearcher));
}
} catch (Exception e) {
throw new IllegalStateException(e);
}finally {
logger.info("warming up consumes ["+(System.currentTimeMillis()-start)+"] Millis");
}
}
class WarmUpDocValueThread implements Runnable{
private String field;
private SolrIndexSearcher newSearcher;
public WarmUpDocValueThread(String field,SolrIndexSearcher newSearcher) {
this.field = field;
this.newSearcher = newSearcher;
}
@Override
public void run() {
try {
DocValues.getSorted(this.newSearcher.getLeafReader(), this.field);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这里先大概解释一下这段代码的业务需求。
由于在业务方进行一个查询工作的时候,发现有一段查询语句的时间抖动非常大,最长耗时可能到6000ms,快的时候在400ms左右。所以组长分析是该查询语句涉及到排序,而solr周期性的softCommit之后,会需要对整个docValue进行重新merge,所以会造成周期性的抖动。所以需要在softComiit之后先进行对docValue的预热。
确定逻辑后,让我上手完成这个逻辑。整个代码逻辑也不复杂,就是写一个eventListener,在init()方法中初始化solrconfig.xml的配置,在newSearcher()方法中对docValue进行预热。
所以写了以上这一版本,在组长review的时候,发现了很多不足,现在记录一下,也是以后尽量避免。
1: 在多线程并发情况下,没有设置主线程的堵塞,及在多线程同时对docValue进行预热的情况下,主线程并不等待预热完成而直接继续执行。针对这个问题,在修改的第一版本中,在多线程开启后,加入thread.join(),完成主线程的等待,在组长的建议下修改成了countDownLatch。这里顺便写一下countDownLatch和join用法的区别。
本质上countDownLatch和join都实现同一个目的,即多线程并发编程时,当各别线程需要等待特定的其他线程任务执行完成后再执行时,用到以上两个方法。具体使用方法这里先不赘述了,主要讲讲不同的使用场景。
在使用join时,阻塞线程必须等待其他线程任务完全结束后才能继续执行,而使用countDownLatch时,可以任意指定其他线程的执行程度。
举个例子,此时有A,B,C三个线程进行任务执行,假设三个线程任务均为执行100的计数且A线程必须等到B,C计数完成再执行,此时用join或者countDownLatch都能完成任务要求。但是如果任务改成,A线程必须等到B,C都计数到50时,再开始执行,此时join不能完成这个要求,但是用countDownLatch时可以实现,即先
CountDownLatch cdl = new CountDownLatch(2)
//A线程
cld.await()
//B线程完成50次计数时
cld.countDown()
//C线程完成50次计数时
cld.countDown()
以上代码即可实现要求,以上仅为伪代码,实际编程时注意要把cld.countDown()写在finally里面,避免有一线程崩溃而造成死锁。
第二个不足在于对代码的可配置化程度上,第一版的代码将代码参数写的过于生硬,很难被以后的代码复用,经过组长提示,对AbstractSolrEventListener源码的阅读发现有一个init方法,可以实现对schema.xml文件的配置参数的读取,果断覆写这个方法,将所需要预热的field配置在xml文件中。
本文主要记录一下这次的经验。
分享到:
相关推荐
用这种方法写代码的时薪是要比普通开发人员便宜的。 利用二元奖励机制实现反思 正如网友所言,Reflexion赋予GPT-4的反思能力和人类的思考过程差不多: 可以简单用两个字来概括:反馈。 在这个反馈过程中,又可以...
需要注意的是,这种全本浏览的方式,也可能是整理的方式,也是我所需要的,就是能够对自己所掌握的知识进行一个系统的整理,这个目前不去实现。 如果简化成为这样一个状态,perCDM不但可以搜索代码,而且可以同时搜索...
比如如何在程序的设计思路和组员进行嵌合,这更本就没可鉴之法,只有不多地对个人的思路进行反思、推敲等,寻找到最合适的平衡点。比如时间上的安排,虽然老师给定了大概的时间安排,但是时间段是可以一分再分的,...
最近用Nodejs + express 写了一个zip文件上传的功能,代码给了别人看,各种吐槽,代码不规范,没有按照eslint,编辑器打开就是各种红色提醒,当然还有其他许多… 第一反应就是反感,后面冷静一想,还是自己做事的...
这是一个网页版的javascript购物网站系统
basic 操作 ,tf 的基本操作 ,应用于垃圾短信的文本分类 , 对数据进行操作
程序员在写Sql代码时,一般是一个人写完之后,一运行可快完事 其它这些是不行的,我们根本没有进行过多用户多线程的测试,如果是100个要,一千个要同时访问,还会有这样的速度吗? 我们自己反思一下是不是有这样的...
对自己深度学习方向的论文有idea,可是工程实践能力跟不上,实验搞不定怎么办? 在做算法工程师的道路上,你掌握了什么概念或技术使你感觉自我提升突飞猛进? 发了6篇SCI的师兄告诉我的秘密:科研工具推荐大合集! ...
说故事的人 在编写代码时,我们会产生许多创意。... 这使开发人员可以反思他们所做的事情,写下他们的想法并绘制图片以讲述其代码如何演变的故事。 代码注释 代码注释并不总是描述一个人的思想和观念的最佳
记得刚入公司带我的研发哥们能写... 我不得不停下脚步,开始反思和总结出现这种现象的原因。如果你手上不忙并且感兴趣,请听我慢慢道来。 下面是一个经典的系统权限数据库设计,作为例子来展开论述。 组织
额外给新人的建议:面试题,不是死记硬背的,需要从中悟出道道来, 为什么很多公司都重复问相似的问题(恰恰是可能你写代码会出问题的部分,或者不一定最难,但值得反思的问题), 掌握了这些规律,或者你深入思考了...
写在开头: 最近在做关于地图的小程序,然后就发现了各种...代码如下: initMarkerData(){ let _this = this; let markerList = []; for (let i in _this.data.listData){ let poiInfo = _this.data.listData[i];
他承接着丰富的代码资产(Perl 5),并在 对 通用编程的不断反思中,续写又一个 25 年的辉煌(Perl 6)。 尽管如此,Perl 语言提供的强大特性还是未能得到现存大部分 Perl 5 程序的充分利用。你 可以 写出与Perl 4(或...
原先的框架系统,思路是将自动化代码,通过调用控件的 最近对测试框架进行了重构,也对其中原有的一些设计进行了反思。其中不免有一些自我感觉得意之处,因此写出来和大家分享。这是一个重构的过程,所以将以重构...
- 最高跑分 66w TPS (尝试了一下分bucket对数据进行操作,代码太乱,不放上来了) ### 赛后的反思 ### - 其实可以使用ByteBuffer先把数据读入缓冲区,然后再刷入磁盘,按块写入的效率会相对高些(利用操作系统DMA) ...
事后,自我感觉对这个人脸检测还是不够具体,所以自己抽了一下午的时间用opencv实现图片与视频中的人脸检测,下面是我用vs2013加opencv4.9来实现的。做一下声明,我的代码是参考OpenCV实现人脸检测的一个博客写的,...
但是我已经具备了看到一大段代码,自己对其中的部分语句进行修改,为我 所用,实现自己想要的功能。对于建模比赛来说,达到这种水平一般来说是够用 了,只要在编程同学写程序的时候,建模的同学可以检查 MATLAB 代码...
忽略大小写Replace效率瓶颈IndexOf 随机排列算法 理解C#中的委托[翻译] 利用委托机制处理.NET中的异常 与正则表达式相关的几个小工具 你真的了解.NET中的String吗? .NET中的方法及其调用(一) 如何判断ArrayList,...
Hannah Desmond –投资组合 这些作品集是我在编码训练营Makers Academy学习的证据...我写的代码很容易更改 我可以证明我的工作方式 我合作成长 每周目标与思考 [第3周] 专案 牡蛎卡 带走 战斗 剪刀石头布 Craft.io流程