代码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的反思能力和人类的思考过程差不多: 可以简单用两个字来概括:反馈。 在这个反馈过程中,又可以...
### 如何更好地学习写代码 #### 一、面对编译错误和挑战时的应对策略 在编程学习过程中,经常会遇到的一大挑战就是面对大量的编译错误。这种情况通常是因为对语法不够熟悉所导致的。这时,我们需要有足够的耐心和...
他的职业生涯和贡献说明了软件工程师的价值不仅仅在于写代码,更在于将个人的热情、专业知识和对代码艺术的追求结合在一起。 总而言之,《代码的艺术》不仅是一篇技术文章,更是对软件工程师职业生活的深刻反思和...
TDD强调先写测试用例再编写功能代码,有助于确保代码的正确性,但可能导致过度测试。 反思XP,作者认为虽然XP在某些方面具有显著优势,如快速响应变化和紧密的客户协作,但同时也存在一些值得讨论的问题。例如,...
4. **反思和总结**:定期回顾自己的代码,分析存在的问题和改进的空间,形成良好的编码习惯。 总之,《每天写出好代码的5个建议03》通过简短的文字传达了提升代码质量的核心理念,即保证代码逻辑的正确性、增强代码...
当达到100000行代码时,程序员通常对自己的编程能力充满信心,能有效应对大部分工作场景,并超越身边大多数同行。 然而,编写1000000行代码并非仅仅意味着熟练度的提升,更是一个深度学习和持续优化的过程。在这个...
通过高效地阅读和分析他人的代码,我们可以学习到新的编程技巧,理解不同编程范式,以及如何写出更优雅、更高效的代码。 首先,代码阅读的起点是对编程语言的基础掌握。了解并熟悉所读代码的语言特性和语法结构是必...
在编程世界中,Visual Basic(VB)是一种深受程序员喜爱的编程语言,尤其对于初学者而言,它的语法简洁、直观。然而,写出高质量的VB代码...通过实践和反思,你可以逐渐打破旧的习惯,形成编写高质量VB代码的新习惯。
### 如何编写无法维护的代码:深入解析与反思 #### 总体概述 本文通过一种讽刺的方式探讨了如何编写难以维护的代码。虽然标题看似戏谑,但实际上文章旨在揭示那些不利于代码可读性和可维护性的做法。对于软件开发...
5. **共享代码**:多个读者和写者线程需共享对存储区操作的函数。 **设计说明书内容:** 1. **设计说明**:包含设计目标、系统配置、所使用的编程语言和工具等。 2. **数据结构与模块**:详细说明程序中数据结构的...
作者通过丰富的实践经验和深入的理论分析,为我们揭示了在软件开发过程中如何有效地运用重构和XP方法,以提高代码质量、提升团队效率,并对这一过程进行反思。 极限编程是一种敏捷开发方法,它强调快速反馈、客户...
分析这些代码可以深化我们对C语言底层机制的理解,同时也能启发我们在编程实践中如何避免写出难以维护的“混乱”代码。 例如,一个常见的混乱代码策略是使用复杂的递归或嵌套循环,这可能会导致阅读难度极大,但...
需要注意的是,这种全本浏览的方式,也可能是整理的方式,也是我所需要的,就是能够对自己所掌握的知识进行一个系统的整理,这个目前不去实现。 如果简化成为这样一个状态,perCDM不但可以搜索代码,而且可以同时搜索...
代码阅读是软件开发中至关重要的一个环节,它涵盖了多个方面的知识和技能,旨在提升开发者对已有代码的理解和改进能力。本讲座"代码阅读方法与代码质量"主要关注如何有效地进行代码阅读,理解代码质量的重要性,并...
其次,【提前设计】和【少写代码】是实现优美代码的关键步骤。在动手编码之前,充分的设计和规划可以帮助减少冗余代码,保持代码结构清晰。当发现代码偏离初衷时,应及时停下,反思并调整,避免代码失控。使用代码...
以下就是写好代码的十个秘诀: 1. **鲁棒性(Solid and Robust)**:确保代码在面对异常、边界条件或不可预见的情况时仍能稳定运行。例如,避免在计算时出现除以零的情况,或者在处理数组时检查边界。 2. **简洁性...
8. **实践与反思**:亲自运行和调试这些代码,可以加深对知识的理解,同时也能锻炼我们的编程技能,学会从实践中学习。 总的来说,这个压缩包文件为我们提供了一个实践和学习《剑指Offer》书中案例的宝贵资源。通过...
6. **控制流**:if语句、switch语句用于条件判断,while、for循环用于重复执行代码,理解它们的结构和用法对编写逻辑代码至关重要。 7. **数组**:数组是存储相同类型数据的集合,理解如何创建、遍历和操作数组对于...
8. **JavaScript设计模式**:了解常用的JavaScript设计模式,如单例、工厂、观察者等,这些模式能帮助你写出可维护和可扩展的代码。 9. **性能优化**:讨论如何通过代码优化、减少HTTP请求、缓存策略等手段提高...