前言


这一单元关于线程安全的作业结束了,在助教提供的接口的帮助以及老师提供的设计模型的指导下,这三次作业还是相对轻松地完成了,中间也没有出现什么bug,可能就是因为简单的逻辑不容易出错吧,可惜两次都由于性能分与a组失之交臂,或许在后续作业中还是应该多在性能优化下做一些工作。


第一次作业


设计思路


这次参考了老师所给的生产者消费者问题,主要设计了电梯类,控制器类,输入器类,主类,电梯类只负责向调度器请求指令,并根据接收到的指令进行上下楼接送人操作,输入器类只负责接受指令并向调度器塞入指令,控制器类负责按照时间顺序从输入器抓取指令,并发送给电梯,这里采用的是傻瓜算法,即做完一条指令再发送下一条指令。同时控制器类还负责电梯类的线程结束。这里让线程安全结束的方法是,输入器类只要接收到文件结尾就结束输入 器线程,并设置一个布尔变量作为输入结束的标志,当输入结束并没有指令继续存在时,电梯线程结束。


基于度量来分析自己的程序结构


程序结构


正如设计思路中所说,采用生产者消费者模式:电梯作为消费者,输入器作为生产者,调度器作为托盘,就构成了整个程序的结构


度量分析

可以看到由于采用的是是简单的傻瓜调度,所以这个程序各个类之间的耦合度非常低,相对来说耦合高一点儿的只有调度器和电梯、调度器和输入器之间关于指令传输的方法。


其他


总的来说这次作业难度不大,主要精力花费在如何在各种输入条件下平稳结束各个进程,采取的方式如前文所说,通过设置表示输入结束以及表示指令队列为空的变量,作为break的条件,跳出while循环,从而结束线程


第二次作业


设计思路


这次仍然要求的是一部电梯,要求电梯能够实现捎带算法或者其他更快的算法。由于电梯的请求到来的情况具有不确定性,导致各种算法都存在性能十分差的极端情况,所以在写这次作业的时候果断选择了按照指导书上的捎带算法:主要是定义了主请求、捎带条件

主请求是:当电梯请求队列不为空时,主请求是到达电梯请求队列时间最长的请求,当电梯请求队列为空的时候,主请求是到达调度器时间最长的请求

捎带条件是:当前主请求与该请求的目的地处于电梯当前位置的同一侧,即可以成为捎带请求

为了能够不混淆会令主请求的人乘坐时间过长的捎带请求,我在程序中规定:电梯只能添加满足捎带条件并且出发楼层与电梯当前位置相同的捎带请求

这样的话电梯的工作流程就是:

主请求为空时:向调度器申请主请求,并去接主请求发出者

每到达一层楼,判断是否需要停留(有无人上下电梯、有无当前楼层可添加的捎带请求)

每当主请求下电梯时就更新主请求

当电梯为空时又重复第一步

同时需要注意的是由于现在一个电梯可装载多个请求,为了避免电梯在装到人之前就下人的情况:

我为每个人设置了状态,上电梯之前的“not in”,上电梯之后是“already in”从而避免了bug出现。


基于度量来分析自己的程序结构


程序结构


由于这次的电梯本质上只需要更改调度器向电梯派发指令的策略,添加判断是否应该停靠、派送捎带请求的方法,所以整个程序总体上结构没有太大变化,代码也基本沿用第一次作业的代码,只做了少量修改。


度量分析


由于基本沿用了上一次作业的代码所以各个类之间的耦合度还是比较低,唯一高一些的是pusubcmd方法,这是由于这个方法要求调度器能够知道电梯当前的位置即已经装载了的指令的情况,所以与电梯类的耦合度较高。


其他


总的来说这次作业难度不大,主要精力花费在如何设计捎带算法的实现,让电梯运行的时候面对各种指令情况不会出现吃人、造人、不停开关门的bug,解决的方法是:

只装载电梯当前位置的捎带指令。

为人设置是否进入电梯的变量。


第三次作业


设计思路


这次要求能够支持三部电梯,并且对电梯定义了运动速度,容量,以及可停靠楼层。难点在于根据每个电梯的可停靠楼层,将无法一次乘坐到达的请求,进行拆分,从而到达。

我采取的策略是:通过逐层分析,所有不能一次到达的请求,都能拆分成两次到达,所以我的拆分策略是拆为出发楼层到离当前最近的中转楼层与从中转楼层到目的楼层。

同时由于拆分后的后半部分指令必须在前一半指令结束后才能执行,所以我采取的策略是将其放入一个暂不可执行队列,当前半部分执行完成后,发送信号将后半部分加入可执行队列。

至于运动速度、容量、可停靠楼层等,都可以通过在电梯类中增加相应的成员变量,与判断条件来实现。

同时这次仍采用和第二次一样的捎带算法。


基于度量来分析自己的程序结构


程序结构


除了增加与指令拆分相关的代码与容量速度等新成员变量,整个程序总体上结构没有太大变化,基本沿用第二次作业的代码,只做了少量修改。


度量分析


这一次的代码耦合情况就不像前两次那么令人乐观了,可以看到又四个方法爆了红:

可以看到向电梯发送指令的两个方法pushmiancmd与pushsubcmd的模块复杂度和循环复杂度都较高,这是由于两者在向电梯发送指令前都需先对调度器内部是否还存在符合各电梯要求的指令进行判断,然后根据电梯可去楼层集判断可否推送该指令,最后还需遍历更新当前调度器内符合各电梯可去楼层集的指令状况。所以需要频繁访问电梯的位置信息、可去楼层集、是否超载,以及循环判断指令情况,所以导致这两项复杂度过高。想要解决这一办法可考虑将这两个方法中的部分代码另写代码封装起来。

同时loadcmd的循环复杂度较高,这是由于我在这部分实现了电梯指令的拆分,由于我是暴力枚举的所有拆分情况,所以判断层数多,循环复杂度很高,可以考虑实现一个一般化的拆分方法,不过可能性能就没有暴力枚举的最佳拆分那么好。


其他


这次的难点在于指令拆分,坑点在于指令拆分后,后半部分指令必须等前半部分执行完后才能进入队列,同时考虑是否已经执行完所以指令时必须考虑被放入暂不可执行队列的指令,否则可能会出现电梯提早被kill的情况。


分析自己的bug


由于采用的都是指导书给出的算法和模型,并且在处理时模拟了真实电梯的各种行为而不是只输出结果,所以这三次作业没有被测出bug。可见简单的算法加贴近实际情况的模拟会使代码十分可靠。


找他人bug的策略


这次找他人bug的策略主要是首先提交自己在写代码过程中出现的bug,看他人是否犯了同样的错误,其次是针对于线程安全可能出现的常见问题,比如不能平稳结束、提前结束等进行测试。此后采用的是选取两三份代码风格不佳的代码,阅读分析其思路,然后反向找逻辑错误。可惜由于这几次在的组都是属于,简单思路与实现,导致代码逻辑显得坚不可摧,所以找bug的效果并不太好。


心得与体会


事实证明,简单明了的算法与模拟现实生活的思路能够构造非常可靠的代码,这也是这几次没出bug的原因。只是可惜,由于性能的缘故,后两次作业的分组情况都不是很理想,后续可能考虑在保证可靠性的情况下,采取一些高性能但复杂的算法,来挑战自己!

转载于:https://www.cnblogs.com/MAXzwq1998/p/10760959.html

OO第二单元作业分析相关推荐

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

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

  2. OO第二单元作业小结

    总结性博客作业 第一次作业 (1)从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略. 第一次作业为单电梯傻瓜调度,可以采用生产者--消费者模型,是一个有一个生产者(标准输入电梯请求),一 ...

  3. BUAA OO第二单元作业总结

    一.作业设计策略 (一)第一次作业设计方案 模型:生产者消费者模型 两个线程:输入线程(生产者).电梯线程(消费者) 共享对象:请求队列 退出模式:输入线程读到null,退出run,并将null传入请 ...

  4. OO第二单元作业总结

    一:设计策略 第一次作业:第一次是单电梯傻瓜调度策略,因此我把调度器当作共享资源对象,有一个put和一个get方法,因为只有一个电梯,并且单次取出和投放一个请求,因此只需要同步控制一下这两个方法是互斥 ...

  5. 多线程编程初探——OO第二单元作业回顾

    一.作业设计策略 1)执行FAFS策略的单部电梯 ​ 由于对多线程不是很了解,于是采用了理论课上介绍的生产者消费者模型作为设计模板(也是很多同学一开始的做法):将请求队列作为共享对象(托盘),名为In ...

  6. OO第二单元电梯作业总结

    目录 目录一.第一次作业分析设计策略基于度量分析程序结构二.第二次作业分析设计策略基于度量分析程序结构三.第三次作业分析设计策略基于度量分析程序结构四.分析自己程序的bug五.发现别人程序bug所采用 ...

  7. 面向对象课程第二单元作业总结

    面向对象课程第二单元作业总结 前言 电梯系列作业分为三个阶段,逐步深入实现越来越复杂的电梯运行状态模拟. 第一阶段实现单部多线程傻瓜调度(FAFS)电梯的模拟: 第二阶段实现单部多线程可捎带调度(AL ...

  8. OO第一单元作业总结

    OO第一单元作业总结 第一次作业 结构 OO第一次作业是简单的多项式求导,在这次多项式求导中,仅包含了幂函数和带符号整数的一些简单求导运算.在经过自己的一些简单分析后,我认为第一次作业最重要的部分是判 ...

  9. OO第二单元(电梯)单元总结

    OO第二单元(电梯)单元总结 OO第一单元(求导)单元总结 这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉理解和掌握多线程的思想和方法.这个单元以电梯为主题,从一开始的最简单的单部傻瓜调 ...

最新文章

  1. Java泛型深入题目
  2. python怎么用数据修改,如何更改数据框Python中的值
  3. Linux下1号进程的前世(kernel_init)今生(init进程)----Linux进程的管理与调度
  4. Redis 一些高级用法
  5. flex布局导致拉伸的问题
  6. 机器学习与计算机视觉(绘图)
  7. 相机标定—了解相机模型
  8. 使用Python下载百度云文件
  9. 如何用Scapy写一个端口扫描器?
  10. Ubuntu安装Adobe Reader
  11. php+mysql新闻发布系统(一)
  12. 堂食扫码点餐的小程序设计开发
  13. 南京旅游迈入大数据时代
  14. navicat导入excel表中数据出错问题
  15. 全国天气预报信息数据接口 API
  16. 宿华卸任快手CEO程一笑接替;新思科技扩大与台积公司的战略技术合作 | 全球TMT...
  17. 2021年中国城市财力半年报 Top 30
  18. dubbo-admin 容器化构建
  19. iPad/Iphone抓包
  20. 不捡肥皂捡贝壳----00

热门文章

  1. 英语计算机班,15计算机班英语第二次月考测试卷(2017).docx
  2. php curl显示错误信息,php如何调试curl错误信息
  3. group by 查询分组后 各组的内部条数与组的条数
  4. Java并发编程之ConcurrentLinkedQueue详解
  5. mybatis-plus控制台打印SQL
  6. swagger访问开关配置
  7. Android开发笔记(一百七十八)更安全的数据仓库DataStore
  8. Android开发笔记(九十三)装饰模式
  9. 加一度分享5大竞价经验,让流量更大更精准
  10. CCIE-交换路由复习笔记