OO第二次博客作业

零、写在前面

OO第二单元宣告结束,在这个单元里自己算是真正对面向对象编程产生了比较深刻的理解,也认识到了一个合理的架构为编程带来的极大的便利。

(挂三次评测分数 看出得分接近等差数列 菜鸡本质暴露无遗)

一、总体设计策略

三次作业设计策略基本相同。前两次是四个类:Main、Elevator、Taker、Waiter;两个线程:main、elevator。第三次在此基础上多了一个类:Dispatcher,一个线程:dispatcher。之所以前两次没有调度器类,是因为由于只有一个电梯所以直接把调度器安在这个电梯内部了。其实算一种偷懒行为。

基本算法是若Taker队列为空,电梯从Waiter队列中取一个主请求,将其送到目的层,然后在途中实现捎带(可以进也可以出);然后送达后若Taker队列非空,则从其中选一个Taker作为新的主请求。调度器的功能是为电梯分配相应的Waiter队列。

由于架构合理,三次作业没有出现重构现象。

本来想在第三次作业的调度器类采用单例模式,但是实现上出现了一些问题,于是没有采用(后来证明并不是单例模式的问题,而是线程安全的问题,最基本的ArrayList线程不安全,自己属实智障了)

二、基于度量的分析

第一次作业

总体结构分析

第一次作业由于是首次接触多线程编程,事实上最初还是遇到了一些语法上的困难的;但是解决了基本的语法问题之后,剩下的算法问题就轻而易举了。(据说第一次100分遍地都是)

但是幸运的是自己在第一次作业便打好了合理的架构,便使得之后两次作业只需要添添补补就可以轻松实现,让自己在这个单元没有尝到重构的滋味。

基本架构:将Request分为Taker和Waiter两类,其中Waiter类要增加一个toTaker方法,其余基本完全对称。而在电梯内部也几乎是完全对称,基本原因就是只有Waiter才能进,只有Taker才能出。但是采用了轮询。

存疑:采用了线程安全的阻塞队列(BlockingQueue),然而相关知识并不十分完备,所以只用了一些最基本的方法(比如poll),还有很多可以深入学习。

复杂度分析


可以看出基本没有红字,这也是我所说的架构合理的一部分。Elevator类里方法过多也是没有办法的事情,因为自己觉得这个实现也非常自然了,实现可能啰嗦一些但是思路是绝对简单清晰的(而且第一次已经实现了捎带)。

第二次作业

总体结构分析

从来没有比第二次作业更轻松的一次了;因为捎带这个事情上一周就写好了,只要稍微改一改数值(而且中测1次AC)。除此之外处理了轮询问题。但是捎带的算法肯定比较low了,因为只有92分的强测成绩。

复杂度分析

可以看出基本上和第一次无甚出入。

第三次作业

总体结构分析

第三次作业终于不能再偷懒了;终于加入了调度器线程。加入调度器线程之后线程交互性大大增加,这也使得这次作业和之前两次出入巨大。但是幸运的是Elevator类基本还是那个Elevator类,也就是说电梯该怎么跑还是怎么跑,接人捎带人都还是电梯的事情,调度器只是为了分配给电梯相应的乘客而已。也算是大大减小了第三次作业的设计难度。但是优化实在是基本形同虚设,还是自己太菜了,性能分基本为零。

复杂度分析

可以看出调度器的加入导致复杂度大大增加,这也是总体结构分析中说的一部分。

SOLID原则

SOLID原则指:单一责任原则、开放封闭原则、里氏替换原则、依赖倒置原则、接口分离原则。

单一责任原则:每个类只负责自己的事情。自己认为做的还不错,挑毛病的话可以是前两次没有调度器,或者说调度器在电梯里。但是单电梯的话,也就没必要去分配乘客,所以是完全可行的。第三次中,调度器只负责分配乘客,电梯只负责运行。

开放封闭原则:软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。三次作业可扩展性很强,事实上,不用重构而只需要修改参数就说明了这一点。而封闭可以将电梯上下行、接送乘客设计为抽象方法,但是本次作业不必要这样做。

里氏替换原则:派生的子类应该是可替换基类的。继承Thread类是唯一的继承,这和设计层面的继承是两个概念。

依赖倒置原则:高层模块不应该依赖低层模块,相反,他们应该依赖抽象类或者接口。也就是强调高层模块的抽象。本次根本不涉及什么高层模块,也就不用管。

接口分离原则:类不应该被迫依赖他们不使用的方法,也就是说一个接口应该拥有尽可能少的行为,它是精简的,也是单一的。三次作业根本没有用接口,就连Thread类也是继承,没有去实现对于Runnable的接口。

三、bug分析和互测策略

bug分析

三次作业没有出现强测的WA点,所以只谈一下编程过程中、最后一次提交前遇到的问题。

其实最主要的还是线程安全问题……这个问题贯穿于三次作业中,主要是,这个问题可能很不起眼,但是却很致命(说的就是你,一个小小的ArrayList不安全花了一个晚上的时间来debug)。而且多线程调试的问题实在是与之前的程序差别太大了,所以尝试了很多调试方法,然后到头来得到了一个真理:printf大法好!(滑稽)

互测策略

互测说实在的,根本没有针对性。屋子里也是要么一片宁静祥和,要么大家象征性地空刀几下。但是互测也不是没有它存在的意义,自己就是在互测中膜了某位巨巨的代码增进了自己对于单例模式的理解(虽然后来没有成功运用到自己的代码之中,但是自己确实深刻感受到这个是好东西啊)。

总的说来,三次作业没有强测bug,没有互测bug,不用bug修复,除了性能分不是太好看之外,属实惬意许多(想起了自己第三次求导bug修复了一天,那种滋味真的酸爽)。

四、心得体会

第一,一定要重视合理架构!尤其是在第一次作业之中。因为第一次作业是最简单的,所以在解决语法问题之后算法问题就轻而易举,那剩下的时间干啥呢,偷懒吗。。或者说,从最开始就思考问题对象最本质的特征,按特征分配类和对象。一个合理的架构会为之后的二、三次作业带来极大的便利。重构一时爽,话是这么说,但相信没人想每次都从头再来吧?

第二,一定要重视线程安全!多线程与单线程编程最大的区别、也是最大的差异就是线程数量的增加(这不是废话么),但也正是因为这是最主要的区别,所以它带来的线程安全bug也就是最大的差异,而别的bug基本都是之前的那种bug了,因此那就无需多提。

五、写在后面

三次作业虽然没有WA点,但是调度算法并没有找到一个太满意的算法。第二次也就是单电梯简单,所以直接类似SCAN算法完事,得分也还不错,估摸着进A组了;第三次轮到多电梯,依旧是SCAN算法就不大好使了,原因就是没找到一个好的分配等待队列的算法,结果就是强测性能分基本为零咯。

抛开分数不谈,通过了这三次电梯作业才真正让自己对面向对象编程思维有了较为深刻的理解,从中稍微窥得OO的本质,也算是自己的很大的一个进步了吧。

OO第二次博客作业—17373247的更多相关文章

  1. OO第二次博客作业——电梯调度

    OO第二次博客作业——电梯调度 前言 最近三周,OO课程进入多线程学习阶段,主要通过三次电梯调度作业来学习.从单部电梯的傻瓜式调度到有性能要求的调度到多部电梯的调度,难度逐渐提升,对同学们的要求逐渐变 ...

  2. OO第二次博客作业(第二单元总结)

    在我开始写这次博客作业的时候,窗外响起了希望之花,由此联想到乘坐自己写的电梯FROM-3-TO--1下楼洗澡,然后······ 开个玩笑,这么辣鸡的电梯肯定不会投入实际使用的,何况只是一次作业.还是从 ...

  3. oo第二次博客作业

    多线程协同与同步控制总结 第五次作业-多线程电梯 本次作业是我第一次接触多线程,建立了请求模拟器.调度器和电梯运行三种线程.请求模拟器负责在输入后识别有效请求:调度器在扫描有效请求后将新的请求加入请求 ...

  4. OO第二次博客作业--第二单元总结

    第一次作业 1. 设计策略 第一次作业,一共三个线程,主线程.输入线程和电梯线程,有一个共享对象--调度器(队列). 调度的策略大多集中到了电梯里,调度器反而只剩下一个队列. 2. 基于度量的分析 类 ...

  5. [BUAA OO]第二次博客作业

    第五次作业 这次作业是电梯系列作业的终极版,要求是使用多线程实现三部电梯的运行.这次作业的难点在于第一次运用多线程技术,对于线程中的行为并不了解,以及电梯功能的实现(如果之前作业采取的是扫描指令队列预 ...

  6. Java第二次博客作业

    Java第二次博客作业 时间过的很快啊,在不知不觉中这门课程的学习也就快要过去一半了,现在就来总结一下在这个第二个月的学习当中存在的问题以及得到的心得. 1.前言 第四次题目集和第五次题目集给我的感觉 ...

  7. 第二周博客作业 <西北师范大学| 周安伟>

    一,本周助教小结 逐步开始适应助教工作,对学生发布的博客进行点评,查看学生对软件工程前期的准备情况. 二,助教本人博客 https://home.cnblogs.com/u/zaw-315/ 三,学生 ...

  8. C语言第二次博客作业---分支结构

    一,PTA实验作业 题目1.计算分段函数 本题目要求计算下列分段函数f(x)的值: 1.实验代码 double x,result; scanf("%lf",&x); if( ...

  9. C语言第二次博客作业——分支结构

    一.PTA实验作业 题目1:计算分段函数 1.实验代码 #include<stdio.h> #include<math.h> int main(void) { double x ...

随机推荐

  1. ElasticSeaarch 遇到的问题 (-)

    1 elasticSearch 不能通过ip访问 智只能通过localhost访问,或者在外网部署的时候不能访问: elasticsearch.yml文件 中将下面的配置去掉注释符,  network ...

  2. 洛谷 P3379 【模板】最近公共祖先(LCA)

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  3. lambada表达式

    在Java 8中stream().map(),您可以将对象映射为其他对象. List<String> collect = alpha.stream().map(String::toUppe ...

  4. configure文件的生成

    https://blog.csdn.net/mitesi/article/details/44773951 make 根据Makefile编译源代码,连接,生成目标文件,可执行文件. make cle ...

  5. 【Python全栈-JavaScript】jQuery效果

    jQuery效果 jQuery 效果函数: 方法 描述 animate() 对被选元素应用“自定义”的动画 clearQueue() 对被选元素移除所有排队的函数(仍未运行的) delay() 对被选 ...

  6. vue + ts @Prop boolean 问题

    假设btn组件有一prop属性radio,声明如下 @Prop({ default: false }) radio!: boolean; 在组件传递 <btn radio /> 此时的 r ...

  7. Mybatis-Plus 3.0代码生成器

    package com.kyplatform.generator; import com.baomidou.mybatisplus.core.exceptions.MybatisPlusExcepti ...

  8. group by 用法解析

    group by 用法解析 group by语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表. SELECT子句中的列名必须为分组列或列函数.列函数对于GROUP BY子 ...

  9. 11、jeecg 笔记之 界面常用整理 - 方便复制粘贴

    1.datagrid 操作按钮(按钮样式) 操作按钮的显示主要依赖于 <t:dgCol title="操作" field="opt"  ></ ...

  10. 玩转Vuejs--数组监听

    Vue中对数据的监听主要是依靠Object.defineProperty来实现的,这种实现主要是针对key/value形式的对象,对数组中值的变化是无能为力的,那么该如何对数组中的数据进行监听呢,下面 ...