第二单元总结

一、作业分析

1.多线程设计与控制

我设计的原则是能少建立线程则尽量不要多建立没有意义的线程,这样多线程相关的设计与控制将更加简洁。关于线程冲突,我主要采用synchronized来进行同步控制,和共享数据相关的方法需要保证其操作原子性的均加上synchronized关键字,为防止电梯等待请求的轮询。使用wait方法。

2.具体架构

我的电梯整体上采用的是look调度原理,既电梯在楼层间扫描,若可以调头,则调头,若有人要上则上人。第二次作业和第一次作业差别不大,我为每个电梯开了一个storage,请求从主线程读入后几乎不访问电梯的情况将请求放入仓库。第三次作业较前两次变动比较大的是需要换乘,我考虑在1、15楼换乘,若电梯无法满足请求则在此抛出请求给其他仓库,此时要增加电梯和其他电梯、仓库的交互,需要比较谨慎,在此我采用hashtable容器来存储电梯与仓库作为共享变量。关于结束程序是个比较难以考虑的点,前两次我都是采用最后放入storage一个特殊的请求,作为输入结束的标志,而第三次由于换乘请求可能在输入结束标志到来后到达,我设计了一个标志来表示电梯是否能够退出,该标志可以让电梯跳过装人环节,当该标志置位时访问其他电梯的情况,若该标志均置位则可以结束线程。

(1)类的度量

下面为三次作业类的度量:

可以看到第一次作业中判断是否要下人和是否需要调头的方法的复杂度较高,而这些方法几乎是必须的,看见这次的复杂度控制的比较好,第二次同第一次作业同第一次类似,修改也较少,变化不大,第三次作业方法增加了许多,但是复杂度几乎没有大的变化,可见三次作业复杂度控制的比较好。

(2)类图

三次作业的类图如下:



三次设计思路类似,类图也看起来差别不大。很明显,三次作业在低耦合这一点上做得还不够好,比如电梯类其实可以简单的只负责上下开门一类的,利用一个单独的控制类来对电梯的行为进行控制,这样也不至于导致电梯类的行数太多,电梯只接受控制器的控制,另外还可以单独构造一个类来储存各个电梯的信息,这样在交互的时候逻辑也比较简单,并且不容易出错。

(3)协作图


由于低耦合做得不好,所以类比较少,只有main、elevatro、storage三个类,类、线程之间的交互也比较简单,三次作业的内核都采用上图所示的方式,电梯每到一个楼层向storage索取请求,如果没有且满足其他一些条件则wait,storage每次get到请求便notifyall,交互逻辑简单,这算是优点,第三次的结束部分增加了满足结束条件则上下游走,等钱其他电梯以确认换乘不会增加请求,此处没有增加wait,当然其实这样的处理不好,只是为了写起来简答,但是对电梯而言就比较累了。

3.设计评估

(1)性能设计

关于性能,我三次都是再之前的基础上满足额外功能要求,基本调度采用look算法,比如第二次当请求到来时我会先获取各电梯线程的状态,若为WAITING则放入对应的仓库,若没有正在WAITNG的电梯则随机放入一个仓库,实现起来比较容易,不涉及电梯信息的交互,分数上还算过得去,算是性价比比较高的写法。第三次的换乘则不得不添加一些电梯间的交互,大体上请求调度也采取随机的方式,分数也还过得去。

(2)设计原则(SOLID

SRP单一责任原则

不得不说我的类之间的耦合度一次比一次高,类之间的分工还算明确,但整个作业不过三个类而已,这一点做得很不好。倒是其中的方法分的比较细,从方法的角度来看还算满足单一责任原则,面向过程的意味比较浓。

OCP开放封闭原则

这一点做得一般,每次写作业还是主要考虑当次作业的需求,习惯性的修改原有的代码,但是我的方法划分比较细,单个方法的独立性较好,方法与方法之间的耦合度较低,因此修改时往往只涉及到部分方法。

LSP里氏替换原则

作业中未涉及继承,当然这是不好的。

ISP接口分离原则

写代码还是不习惯设计接口,可能作业的工程量还不算大。

DIP依赖倒置原则

对于一套仓库和电梯而言,是满足这个原则的,仅仅是在交互时可能发生跨层次交互,总的来讲这一点还是符合的。

(3)可拓展性

写代码时没有意识来实现更好的可扩展性,往往扩展时需要对代码比较熟悉进行修改,毕竟作业的工程量较小,层次划分不够,作业的时间跨度也比较短。当然经过两次迭代的过程,多少有一些扩展性比较好的地方,特别是第三次,因为第三次电梯的种类比较多,类型差异还算比较大,我采用一个构造方法来实现不同的电梯,因此就算新增种类的电梯也能够简单的增加构造方法的逻辑分支即可。关于线程的交互,比如电梯之间的交互,由于我的设计原则是尽量少交互,所以没有实现一个统一的交互平台,这是不足的,影响扩展性。

二、BUG分析

1.我的BUG

第三次作业中电梯会在一些极端的情况出现进入wait之前,条件判断之后触发notify,导致wait无法退出的情况,在调整了判断条件,增加了notify的情况下得以解决。

2.他的BUG

第一次的时候虽然没有hack成功,但是我发现有个同学开门用0.4s,关门用0.4s。。。这告诉我们要认真读题!!!第二次的时候在互测的最后关头发现有个同学的超载处理有问题,会出现电梯的超载的情况,可是时间不够没能成功提交合法的互测样例。。。第三次的时候发现有同学的电梯会卡住,程序无法退出,应该是退出逻辑没有写好。第三次作业常常有不知道为什么非法的构造样例,真的已经仔细看过互测用例要求了还是提交不上去,希望今后能够反馈非法原因。

3.测试相关

我一般会简单读一下代码,如果觉得有问题则想办法构造样例,另外我也写了测评机,随机生成测试用例,如果有问题则分析问题所在。

三、心得体会

要先做设计再开始动手写代码,低耦合高内聚应该深入人心,设计不应该只是针对作业满足作业要求,还应该考虑设计的“美观”(尽量划分层次,从类入手设计,功能考虑完善),这样犯错的概率也更低,效率也更高。这次我了解了多线程,是个很神奇的东西。这次还让我认识到,关于性能分,我的水平还是追求高性价比比较好,特别是对于一些说不清楚的东西,带有随机性的东西。就像我们的人生,不必贪心。

posted @ 2020-04-18 19:49  陈鸿-18373205  阅读(139)  评论(0)    收藏  举报