`
粟谷_sugu
  • 浏览: 25379 次
社区版块
存档分类
最新评论

对自己写的代码的反思

阅读更多
代码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文件中。
    本文主要记录一下这次的经验。
分享到:
评论
1 楼 ZJKAICO 2018-03-21  

相关推荐

    GPT-4写代码能力提升21%!MIT新方法让LLM学会反思

    用这种方法写代码的时薪是要比普通开发人员便宜的。 利用二元奖励机制实现反思 正如网友所言,Reflexion赋予GPT-4的反思能力和人类的思考过程差不多: 可以简单用两个字来概括:反馈。 在这个反馈过程中,又可以...

    PerCM个人代码管理软件

    需要注意的是,这种全本浏览的方式,也可能是整理的方式,也是我所需要的,就是能够对自己所掌握的知识进行一个系统的整理,这个目前不去实现。 如果简化成为这样一个状态,perCDM不但可以搜索代码,而且可以同时搜索...

    考勤系统数据库课程设计(报告含代码).doc

    比如如何在程序的设计思路和组员进行嵌合,这更本就没可鉴之法,只有不多地对个人的思路进行反思、推敲等,寻找到最合适的平衡点。比如时间上的安排,虽然老师给定了大概的时间安排,但是时间段是可以一分再分的,...

    vscode 使用Prettier插件格式化配置使用代码详解

    最近用Nodejs + express 写了一个zip文件上传的功能,代码给了别人看,各种吐槽,代码不规范,没有按照eslint,编辑器打开就是各种红色提醒,当然还有其他许多… 第一反应就是反感,后面冷静一想,还是自己做事的...

    jsp+servlet+mysql写的简易购物网站系统代码

    这是一个网页版的javascript购物网站系统

    Untitled_垃圾短信分类_垃圾短信_python_Untitled_

    basic 操作 ,tf 的基本操作 ,应用于垃圾短信的文本分类 , 对数据进行操作

    C#多线程|匿名委托传参数

    程序员在写Sql代码时,一般是一个人写完之后,一运行可快完事 其它这些是不行的,我们根本没有进行过多用户多线程的测试,如果是100个要,一千个要同时访问,还会有这样的速度吗? 我们自己反思一下是不是有这样的...

    论文写作/学习经验合集

    对自己深度学习方向的论文有idea,可是工程实践能力跟不上,实验搞不定怎么办? 在做算法工程师的道路上,你掌握了什么概念或技术使你感觉自我提升突飞猛进? 发了6篇SCI的师兄告诉我的秘密:科研工具推荐大合集! ...

    storyteller:讲讲代码如何演变的故事

    说故事的人 在编写代码时,我们会产生许多创意。... 这使开发人员可以反思他们所做的事情,写下他们的想法并绘制图片以讲述其代码如何演变的故事。 代码注释 代码注释并不总是描述一个人的思想和观念的最佳

    撸一段SQL?还是撸一段代码?

    记得刚入公司带我的研发哥们能写...  我不得不停下脚步,开始反思和总结出现这种现象的原因。如果你手上不忙并且感兴趣,请听我慢慢道来。  下面是一个经典的系统权限数据库设计,作为例子来展开论述。  组织

    史上最全程序员面试题搜集(intel Cisco、华为、Juniper 微软 摩托罗拉)

    额外给新人的建议:面试题,不是死记硬背的,需要从中悟出道道来, 为什么很多公司都重复问相似的问题(恰恰是可能你写代码会出问题的部分,或者不一定最难,但值得反思的问题), 掌握了这些规律,或者你深入思考了...

    小程序之地图Map反思

    写在开头: 最近在做关于地图的小程序,然后就发现了各种...代码如下: initMarkerData(){ let _this = this; let markerList = []; for (let i in _this.data.listData){ let poiInfo = _this.data.listData[i];

    modern_perl_a4.pdf

    他承接着丰富的代码资产(Perl 5),并在 对 通用编程的不断反思中,续写又一个 25 年的辉煌(Perl 6)。 尽管如此,Perl 语言提供的强大特性还是未能得到现存大部分 Perl 5 程序的充分利用。你 可以 写出与Perl 4(或...

    自动化测试框架:设计的重构

    原先的框架系统,思路是将自动化代码,通过调用控件的  最近对测试框架进行了重构,也对其中原有的一些设计进行了反思。其中不免有一些自我感觉得意之处,因此写出来和大家分享。这是一个重构的过程,所以将以重构...

    2018阿里巴巴中间件挑战赛-消息队列存储引擎题目设计基于Java.zip

    - 最高跑分 66w TPS (尝试了一下分bucket对数据进行操作,代码太乱,不放上来了) ### 赛后的反思 ### - 其实可以使用ByteBuffer先把数据读入缓冲区,然后再刷入磁盘,按块写入的效率会相对高些(利用操作系统DMA) ...

    opencv实现图片与视频中人脸检测功能

    事后,自我感觉对这个人脸检测还是不够具体,所以自己抽了一下午的时间用opencv实现图片与视频中的人脸检测,下面是我用vs2013加opencv4.9来实现的。做一下声明,我的代码是参考OpenCV实现人脸检测的一个博客写的,...

    2017数学建模国赛+深圳杯优秀论文

    但是我已经具备了看到一大段代码,自己对其中的部分语句进行修改,为我 所用,实现自己想要的功能。对于建模比赛来说,达到这种水平一般来说是够用 了,只要在编程同学写程序的时候,建模的同学可以检查 MATLAB 代码...

    asp.net知识库

    忽略大小写Replace效率瓶颈IndexOf 随机排列算法 理解C#中的委托[翻译] 利用委托机制处理.NET中的异常 与正则表达式相关的几个小工具 你真的了解.NET中的String吗? .NET中的方法及其调用(一) 如何判断ArrayList,...

    文件夹

    Hannah Desmond –投资组合 这些作品集是我在编码训练营Makers Academy学习的证据...我写的代码很容易更改 我可以证明我的工作方式 我合作成长 每周目标与思考 [第3周] 专案 牡蛎卡 带走 战斗 剪刀石头布 Craft.io流程

Global site tag (gtag.js) - Google Analytics