OO的第二单元是讲多线程的协作与控制,三次作业分别为FAFS电梯,ALS电梯和三部需要协作的电梯。三次作业由浅入深,让我们逐渐理解多线程的工作原理和运行状况。

第一次作业:

  第一次作业是傻瓜电梯,也就是完全不需要考虑捎带策略,只需要简单的把每一个人都送到目的楼层就可以。与以往写过的程序不同的是,这次要采取多线程的 模式,输入和输出并不同时,输入是按照时间投放的,输出也要包含时间信息。这次作业主要是想教会我们生产者——消费者模型的使用。然而,在第一次写这次作业的时候,我把输入当成生产者,调度器当作托盘,却把每一条请求都当作了一个消费者,试图让每一条指令单独去跑(这或许就是我对多线程最初的理解,然而其实这次作业中的多线程是让我们将输出和输入两个线程并发执行),导致出现了很离谱的错误。并且,在试图保证每两条请求的运行不能够出现重叠,我还想在调度器中设置该条指令是否结束的标志位,这个方法看上去是可行的,但是我当时对于notifyALL,wait等还不是很理解,甚至想尝试在run()方法的最后加入notifyALL(),企图来唤醒正在等待的线程,发现根本无动于衷23333,最后我甚至想到了wait(100)再去查询的zz方法,虽然这样能够跑出来,但是这是一个浪费CPU的轮询,而且线程会频繁的被唤醒然后wait。最终,在我积极的与同学交流的过程中,终于慢慢理解了这道题的本意,将其改成了输入生产者,输出消费者,变成了比较正常的思路。但改完之后,我还是遇到了问题,那就是怎么样让他停下来。输入线程根据给的样例遇到null就会停,那输出怎么办。于是,我在输入线程遇到null停止之前把null也传进来,输出线程遇到null也停止,这样终于搞定了第一次作业。

类图如下:

度量分析如下:

可以看出,这次由于正确的采用了生产者消费者模式,所以各个类和方法的复杂度都比较低,设计的比较好。

第二次作业:

  第二次作业是als电梯,也就是要采取捎带策略的电梯。指导书中给的捎带方法为将与主请求同一方向的请求作为捎带请求加入,并且不断地去更新主请求。我采用的方法是将第一条请求作为主请求,然后将与他同方向的,并且是当前运行到的楼层可以携带的请求全部加到电梯运行的请求队列中,然后将电梯请求队列中的请求都跑完并且电梯中没有人作为一次主请求及其捎带请求跑完的判断条件。我觉得不断升级主请求和我采用的方法实现起来的结构是基本一样的。由于在电梯开关门以及每到一层都可能会输入能够捎带的请求,所以在每一次电梯开关门上下层,我都会判断一次是否有能够捎带进来的请求。这种方法会有不停的对请求队列遍历去查找的问题,不过貌似对40条指令的遍历并不会太占CPU。然而,大闸蟹还是在强测中因为一个小小小小小小小的问题,被炸掉了一大半0.0。在判断捎带的时候,我采用的是判断读到的请求的进入楼层>=当前楼层并且方向向上,以及进入楼层<=当前楼层并且方向向下这样的条件来判断的,为了节省字符数,满足checkstyle,我将这些if分开嵌套,然后就出现了在刚刚上去到达的楼层开始有一堆请求要向下,但是这些请求进的都是>=的那个if,导致并没有带着他们走下去0.0。

  对于优化,我想了这几种策略。一是在去接主请求的路上可以把能够在主请求楼层之前出去的请求先送过去,以此来解决那些上来就16-1,后面却跟着一些1-2,1-3之类的测试点。对于寻找主请求的时候,如果只是找第一条作为主请求,那么15-1,16-1,17-1这样的就会不停的上下,所以在寻找主请求的时候我也尽可能让它一次性能够覆盖到足够多的请求,来节省时间。(然而再怎么优化,由于上面那个小小小小小小小的问题我还是凉了)。

类图如下:

度量分析如下:

可以看出,架构基本和第一次一样,但是由于我在每一次开关门以及每一层上下楼都去判断是否有捎带的请求,导致电梯线程的复杂度较高。

第三次作业:

  第三次作业是三台电梯一起运行,各自有各自的可达楼层,有各自的载客量,对于某些请求,还需要让乘客换成(这难道不是乘客应该考虑的事情吗2333,还有那诡异的残次品C电梯以及只有C才能到达的神秘三楼)。我大致采用了之前的架构,在get方法中增加了对于电梯名字以及是否是该架电梯可以送的人的判断。为了处理换乘问题,我新建了一个类,其中包含两个PersonRequest对象,用来拆分开需要换乘的请求。在执行一条请求时,判断其中第二个PersonRequest对象是否为null,不是的话就将其压到调度器的队列里面。

  怎么样让电梯停下来是我本次作业遇到的最难的问题。由于我之前都是往里面压null,读到了才停,而这一次,如果依旧是读到null停的话可能会在之后分来出来的请求无法执行,会被炸掉。于是我就想让读到null不停下也不拿走,而是更改标志位空跑,知道分离过的请求全部跑完才去停。然后我就发现会有一个请求一直在跑null= =。既然这样,那我就让null被拿走,然后输入null的时候多输入两个,我以为这样三个电梯都会读到null停下来,然而,有一个电梯会把所有的null都抢走然后就没有然后了= =。最终,我发现,为什么要在输入的时候搞进去null呢,我为什么不再所有要分离的指令都搞定的时候再插入null让电梯停下来...菜到流泪(⊙﹏⊙)

  然而,最让我想不到的是,又有一个小小小小小小小的bug炸掉了我强测一大半的点。我在有一个电梯中用来计人数的计数器忘记了清零= =。而且所有炸我的还全部是随机生成的数据,甚至被同学hach14次也全部都是随即数据乱炸0.0。de掉这个bug甚至用了一天。真是写程序不细心,debug两行泪 ┭┮﹏┭┮

类图如下:

度量分析如下:

可以看出,架构其实还是差不多的,只是原来是用PersonRequest现在变成了我自己新建的类,并且输出采用了加锁的静态方法。

由于和第二次架构基本一样,复杂度高的地方也基本一样。

 BUG分析:

  这三次作业,我自己的bug大都是不细心导致的。(然而都是小bug却导致了大问题,非洲人无话可说0.0)

  对与寻找别人的bug,第一次作业,大家都不怎么会测并且傻瓜电梯实在是难出bug,随意根本没有hack到别人。第二次作业,我大部分采用的是我自己遇到的bug,比如停不下来,比如某些捎带请求拿了进去却没办法跑,成功发现了一台能够上天堂的电梯和一台吃人的电梯。第三次作业,我认为大家跑应该是没有问题的,大部分的问题是某些情况停不下来(然而我自己却是跑丢了0.0,或许我找的方向不怎么对),于是我采用了随机数据去测试其他人看能否停下来,停不下来才交,结果只发现了很少的错误,而同组的barsaker是直接交随机数据,结果却炸掉了好多好多人,(虽然全部是同质)。

体会与感想:

这一单元给我的感想是,写的时候开开心心,出分的时候想沙河主楼跃解千愁。但不管怎么样,对于多线程还是逐渐理解了的。多线程的这种不确定性,bug的不可复现性也大大大大大大锻炼了我们的debug能力。这一单元的测评还是比较严格的,虽然像我这种的非到小bug炸全家的不多见,并且好像也找不出什么能够拯救我这种每次都是因为一点点点点小bug被大面积炸的可怜孩子(非洲人无话可说)。

总而言之,这一单元是有挑战的一单元,也是极大锻炼我们能力的一单元。

大闸蟹的OO第二单元总结的更多相关文章

  1. oo第二单元作业总结

    oo第二单元博客总结 在第一单元求导结束后,迎来了第二单元的多线程电梯的问题,在本单元前两次作业中个人主要应用两个线程,采用“生产者-消费者”模式和共享数据变量的方式解决问题.在第三次作业中加入多个电 ...

  2. OO第二单元优化博客

    OO第二单元优化博客 第五次作业没有性能分,但是,我在这一单元的宗旨就是写一个日常生活中 最常见的那种电梯,所以第五次我没有写傻瓜电梯,而是直接写了个\(look\),和第六次基本相同. 总计一下lo ...

  3. 【OO学习】OO第二单元作业总结

    OO第二单元作业总结 在第二单元作业中,我们通过多线程的手段实现了电梯调度,前两次作业是单电梯调度,第三次作业是多电梯调度.这个单元中的性能分要求是完成所有请求的时间最短,因此在简单实现电梯调度的基础 ...

  4. OO第二单元小结

    OO第二单元小结 一.三次作业代码分析. 1.第一次作业 第一次作业是单部电梯的傻瓜调度,由于其过分傻瓜,所以第一次作业我只有两个类,一个main,一个电梯,main类负责不断从输入流中读取命令,如果 ...

  5. OO第二单元多线程电梯总结

    OO第二单元多线程电梯总结 第一次作业 设计思路 Input为输入线程,负责不断读取请求并将读到的请求放入调度器中. Dispatcher为调度器,是Input线程和Elevator线程的共享对象,采 ...

  6. 电梯也能无为而治——oo第二单元作业总结

    oo第二单元作业总结 一.设计策略与质量分析 第一次作业 设计策略 在第一次作业之前,我首先确定了生产者--消费者模式的大体架构,即由输入线程(可与主线程合并)充当生产者,电梯线程充当消费者,二者不直 ...

  7. 2020北航OO第二单元总结

    2020北航OO第二单元总结 前言 本单元考察基于多线程的电梯调度问题,成功让我从一个多线程小白到了基本掌握了使用锁来控制线程安全的能力,收获颇多(充分体验了迷茫地de一个又一个死锁bug的痛苦). ...

  8. OO第二单元——多线程(电梯)

    OO第二单元--多线程(电梯) 综述 第二单元的三次联系作业都写电梯,要求逐步提高,对于多线程的掌握也进一步加深.本次作业全部都给出了输入输出文件,也就避免了正则表达式判断输入输出是否合法的问题. 第 ...

  9. OO第二单元作业总结【自我反思与审视】

    第二单元作业的完成史,就是一部心酸的血泪史…… 多线程的出现为我(们)打开一片广阔的天地,我也在这方天地摸爬滚打,不断成长!如果说第一单元之前还对Java语法有所了解的话,那么这单元学习多线程则完全是 ...

随机推荐

  1. linux 常用命令脑图

  2. MacOS开启PPTP协议

    ​ 开启PPTP协议: Mac OS X 系统默认开启了完整性保护(System Intregrity Protection,SIP),所以即使是root帐户也无法修改系统目录中的文件.如果需要修改受 ...

  3. python库--flask--创建嵌套蓝图

    这里没有对内容进行py文件分割, 可以自己根据框架自己放入对应位置 以下代码生成一个 /v1/myapp/test 的路由 from flask import Flask app = Flask(__ ...

  4. 找不到方法:“Void System.Data.Objects.ObjectContextOptions.set_UseConsistentNullReferenceBehavior(Boolean)

    找不到方法:"Void System.Data.Objects.ObjectContextOptions.set_UseConsistentNullReferenceBehavior(Boo ...

  5. mac下使用vscode技巧

    1.查找 command +  F 2.查找并替换 选中要替换的文字  再 command +  options + F 3.竖状区域部分替换 鼠标点中替换字段的开头或者结尾,按options + s ...

  6. 深入浅出 BPF TCP 拥塞算法实现原理

    本文地址:https://www.ebpf.top/post/ebpf_struct_ops 1. 前言 eBPF 的飞轮仍然在快速转动,自从 Linux 内核 5.6 版本支持 eBPF 程序修改 ...

  7. 还不知道PHP有闭包?那你真OUT了

    做过一段时间的Web开发,我们都知道或者了解JavaScript中有个非常强大的语法,那就是闭包.其实,在PHP中也早就有了闭包函数的功能.早在5.3版本的PHP中,闭包函数就已经出现了.到了7以及后 ...

  8. PHP中的输出缓冲控制

    在 PHP 中,我们直接进行 echo . 或者 print_r 的时候,输出的内容就会直接打印出来.但是,在某些情况下,我们并不想直接打印,这个时候就可以使用输出缓冲控制来进行输出打印的控制.当然, ...

  9. dede织梦会员模板调用template下模板head.htm方法及解析变量

    1.找到dedecms会员中心的的目录 member ,然后在目录下用编辑器打开config.php 加入对dede模板解释函数如下:   //php脚本开始 //引入arc.partview.cla ...

  10. GCN数据集Cora、Citeseer、Pubmed文件分析

    简介 本文将对Cora.Citeseer.Pubmed 数据集进行详细介绍 Cora.Citeseer.Pubmed 数据集 来源 图 节点 边 特征 标签(y) Cora "Collect ...