(一)第五次作业

一、设计思路

生产消费者模型,输入接口是producer,调度器是tray,电梯是customer。由于只有一架电梯,所以生产消费模型满足以下条件:

  1. 一个生产者,一个消费者
  2. 托盘不为空时,消费者可以取走请求。任何时候,生产者可以添加请求。(托盘无容量限制)

互斥:生产者——生产者,消费者——消费者。

同步:生产者至少生产一次,消费者才能消费。

互斥问题我给get和put函数加了方法锁。

二、调度策略:FAFS傻瓜电梯

遵循先到先服务,所以调度器作用很小,只是完成托盘的功能。调度器内部有一个请求队列,还有put和get方法。输入接口和电梯是两个线程。输入接口每收到一个请求,即时加入到调度器队列里。电梯每执行完一个请求,向调度器索要下一个请求。

三、类图

四、度量分析

五、Bug分析

如何结束电梯线程?

调度器里面有一个close变量标志是否收输入结束了。输入接口(使用put函数)传入为null的请求时,调度器会将close变为有效。电梯执行完最后一个任务,get下一个请求。如果此时请求队列为空,且close有效,电梯也结束线程。

但最开始,我把结束电梯的条件写错了,只要close有效就会结束。但可能还有请求没来得及读进调度器队列。正确的get函数写法是,如果请求队列为空且close无效,说明输入没有结束,还要等待后面的请求,就先wait。不再满足wait条件的时候,如果队列仍为空且close变为有效了,就结束电梯。

第二个问题是,输入结束时,我没有调用put方法,而是单独调用一个end函数改变close状态。这样会有一种情况:最后一个请求还在put函数里没有进入请求队列,但后面被紧接着调用了end函数把close置位了,此时也是请求队列为空,close有效,最后一个请求就没有执行。解决方法是,结束输入时,依然调用put函数,传入一个为null的请求。Put函数有synchronized修饰,必须一次一次调用。

六、互测bug

此次作业比较简单,没有发现互测的bug。

(二)第六次作业

一、设计思路

仍然是生产消费者模型,与第一次作业类似。

二、调度策略:ALS可捎带电梯

在调度器里增加了一个flush函数。电梯用get方法得到第一个请求,称为主请求。在去主请求fromfloor的过程中不捎带,从from到tofloor时,每到达一层,用flush函数向调度器索要可以捎带上的请求。捎带条件是,捎带请求与主请求同方向,且捎带请求的fromfloor在电梯当前floor到destination之间。Destination的初值是主请求的tofloor,在电梯每次收到捎带请求的时候更新为主请求和捎带请求tofloor里面更远的那个。

一开始我的电梯在到达主请求fromfloor的时候也可以捎带,但是捎带条件极其复杂,使用的不是destination,而是highestFromFloor,highestToFloor这些变量作为运动的终点。考虑到对第三次作业的可拓展性,我放弃了复杂的捎带策略,但也因此没有拿到性能分。

三、类图

四、度量分析

五、bug分析

从第一次作业直接移植进出电梯的方法,出现了同一个人进两次电梯的问题。所以我在电梯类里面设置了两个请求队列,一个是还没进电梯的请求,一个是在电梯里面的请求,解决了这个问题。

如果在0秒出现两个从1层进电梯的请求,我最初的写法不能捎带上第二个请求。在电梯刚到达一层,和开门之后都向调度器索要可以捎带的请求,解决了这个问题。

六、互测bug

没有发现同组的bug。调度策略越慢,越不容易出现bug,传统的捎带策略最保险。

(三)第七次作业

一、设计思路

在调度器里,给每个电梯设置一个队列。输入接口传入一个请求的时候,调度器根据分配策略分配给一个电梯队列。

二、调度策略

调度器分配请求的原则是,优先分配给能直达的电梯,都能直达的时候优先级A>B>C。否则调用transfer函数,进行换乘分配。

电梯从调度器属于自己的队列里取请求,和查看捎带请求。

关于换乘

将换乘请求分成两个,分配给两部电梯。

其中一个难点是,确保完成换乘的第一站,再开始第二站。我新建了一个TransferRequest类保存换乘请求的id,负责第一站的电梯,第二站的电梯。将一个换乘请求分配好,就设置一个对应的TransferRequest,存入换乘队列。当完成第一站请求(即人走出电梯)的时候,把它从换乘队列删除(transfered函数),执行第二站的电梯检测到队列里没有这个换乘请求了(检测函数为transfering函数),才能执行第二站。

三、类图

四、度量分析

五、bug分析

我设计初期的bug围绕着一个问题:电梯get第一个请求的时候,何时wait,何时结束运行?

Wait的时机是,电梯的请求队列为空且输入没有结束,或者输入结束电梯请求队列不为空但所有都是没完成第一站的换乘请求。相对的,每次输入新请求和完成换乘第一站的时候,都要notify。

结束运行的时机还是,请求队列为空,且输入关闭。

六、互测bug

最常见的问题是多步电梯造成的线程冲突。有些同学让三部电梯同时从一个请求队列里抢请求,多个函数都会修改请求队列,但没有严格互斥。除了请求队列,三部电梯还有其他共享数据,对所有共享数据访问的时候产生混乱。

(四)个人总结

我发现电梯的调度策略越简单,可拓展性就越强,从第二次到第三次作业,我写的非常快,因为捎带的调度策略完全不用修改,电梯类只增加了载客量,速度这两个属性。

但是如果想达到比较有效的优化,就要从LOOK模式转变成SCAN模式,工作量指数型增长。

SOLID原则:

  1. 单一责任原则:在电梯类里,有goUp,goDown,openDoor,closeDoor,peopleMove函数符合单一职责原则,但是operate函数在while循环里反复调用这五个小函数,条件比较复杂,显得臃肿。
  2. 开放封闭原则:作业二到三的扩展很方便,电梯的载客量和速度作为一个属性,增强了扩展性。
  3. 里氏替换原则:第三次作业里面A,B,C电梯是电梯类的实例,避免大量复用。但是由于电梯作业结构简单,三次都没有用到继承。
  4. 接口分离原则:没有用到接口
  5. 依赖倒置原则:调度器里有电梯的引用,电梯里有调度器的引用。

OO电梯作业总结的更多相关文章

  1. OO——电梯作业总结

    目录 电梯作业总结 程序结构与复杂度的分析 第一次作业 第二次作业 第三次作业 程序BUG的分析 互测 自动评测 有效性 总结 电梯作业总结 程序结构与复杂度的分析 第一次作业 1.设计思路 第一次作 ...

  2. OO第三次电梯作业优化

    目录 第三次电梯作业个人优化 前言 优化思路 一.调度器 二.电梯 第三次电梯作业个人优化 前言 由于个人能力有限,第二次电梯作业只能完成正确性设计,没能进行优化,也因此损失了强测分数,于是第三次电梯 ...

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

    前言 本单元作业主要以设计电梯来实现多线程编程.本章主要学习了如何使用多线程以及如何确保多线程安全,从电梯的调度策略中学会了如何简单地使用synchronized锁来控制线程安全. 首先,明确锁的两个 ...

  4. 从入门到不放弃——OO第一次作业总结

    写在最前面: 我是一个这学期之前从未接触过java的小白,对面向对象的理解可能也只是停留在大一python讲过几节课的面向对象.幸运的是,可能由于前三次作业难度还是较低,并未给我造成太大的困难,接下来 ...

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

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

  6. OO第一次作业总结

    OO第一次学习总结 1.第一次作业:多项式加法 从未接触过java的我,在从输入输出开始学了几天后,按照C语言的思路,写出了一个与面向过程极其接近的程序. 在这个程序中,存在两个类:一个是Comput ...

  7. 学会拒绝,是一种智慧——OO电梯章节优化框架的思考

    在本章的三次作业里,每次作业我都有一个主题,分别是:托盘型共享数据.单步电梯运行优化.多部电梯运行优化,因而电梯优化实际是第二.三次作业.虽然后两次作业从性能分上看做得还不错,但阅读其他大佬博客,我深 ...

  8. OO电梯系列总结与反思

    目录 前言 HW5 度量分析 UML类图与协作图 bug分析 HW6 度量分析 UML类图与协作图 bug分析 HW7 度量分析 UML类图与协作图 bug分析 SOLID原则 感想 前言 紧张刺激的 ...

  9. oo第一次作业

    前言: 这是一篇面向对象作业总结,作业内容是对多项式进行求导,一共有三个阶段,具体要求不详述,第一阶段只要求’+’连接coeff*x^pow的形式,第二次支持*连接的幂函数及三角函数,第三次则需要支持 ...

随机推荐

  1. 注释swap分区

    grep  "#" fstab |grep "swap" >/dev/null || sed -i 's/^.*swap/#&/g' fstab

  2. 洛谷P1125——笨小猴(简易模拟)

    https://www.luogu.org/problem/show?pid=1125 题目描述 笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼.但是他找到了一种方法,经试验证明,用这种方法去 ...

  3. C++ windows 函数讲解(一)获得屏幕分辨率

    先上代码: #include<bits/stdc++.h> #include<windows.h> using namespace std; int main() { int ...

  4. umi request 请求资源库详解

    umi-request: 网络请求库,基于fetch封装,兼具fetch 和 axios 的所有特点,具有缓存,超时,字符编码处理,错误处理等常用功能. 1 支持url 参数自动序列化. 2 post ...

  5. PHP中非常好玩的Calendar扩展学习

    为什么说这个 Calendar 扩展很好玩呢?因为你基本用不到它!这个扩展是一套关于日期历法的扩展,但是对于我们来说,它没有农历的相关操作,所以对于我们中国人来说这个扩展并没有什么实际的作用.不过这并 ...

  6. Chrome插件 - Modify Headers for Google Chrome(IP欺骗)

    前景: 该篇随笔的由来:公司某项目(B/S架构)最近新加了一个后台日志功能,需要抓取到访问项目的主机IP,记录目标主机的操作,因此就需要不同得IP访问.并且项目专用浏览器是Chrome内核. Modi ...

  7. git 操作 :从远程仓库gitLab上拉取指定分支到本地仓库;git如何利用分支进行多人开发 ;多人合作代码提交实践

    例如:将gitLab 上的dev分支拉取到本地 git checkout -b dev origin/dev 在本地创建分支dev并切换到该分支 git pull origin dev 就可以把git ...

  8. Jupyter lab 配置记录,xpython + R 语言

    install.packages(c("repr", "IRdisplay", "evaluate", "crayon" ...

  9. Java安全之ClassLoader

    Java安全之ClassLoader 类加载机制 Java中的源码.java后缀文件会在运行前被编译成.class后缀文件,文件内的字节码的本质就是一个字节数组 ,它有特定的复杂的内部格式,Java类 ...

  10. 动图图解GC算法 - 让垃圾回收动起来!

    原创:码农参上(微信公众号ID:CODER_SANJYOU),欢迎分享,转载请保留出处. 提到Java中的垃圾回收,我相信很多小伙伴和我一样,第一反应就是面试必问了,你要是没背过点GC算法.收集器什么 ...