(一)第五次作业

一、设计思路

生产消费者模型,输入接口是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. CGLib浅析

    CGLib浅析 什么是CGLib CGLIB实现动态代理,并不要求被代理类必须实现接口,底层采用asm字节码生成框架生成代理类字节码(该代理类继承了被代理类). 所以被代理类一定不能定义为final ...

  2. 管理后台界面 详细分析(内含代码 |【前端】)RuoYi

    最近在做的一个后台管理 因为关于隐私原因 只方便展示个别页面代码 不会上传项目 注意是前端代码 我把项目代码地址放在最后了 如有需要可自取学习   我会为各位兄弟详细的介绍其中各个属性的含义和用法,记 ...

  3. CodeForce-782B The Meeting Place Cannot Be Changed(高精度二分)

    https://vjudge.net/problem/CodeForces-782B B. The Meeting Place Cannot Be Changed time limit per tes ...

  4. Python程序调用摄像头实现人脸识别

    使用简单代码实现摄像头进行在线人脸识别 import cv2 import sys import logging as log import datetime as dt from time impo ...

  5. Thinkphp5 主动式 计划任务 支持windows和linux

    百度搜索过相关的php计划任务的资料,特别是搜索thinkphp的计划任务,目前能明确实现的都是被动式的,就是通过tp3.2自带的计划任务类实现,通过挂钩子的形式,用户访问网站的时候就执行计划任务,这 ...

  6. 【tp6】解决Driver [Think] not supported.

    使用助手函数view时会出现 解决方法:使用composer安装composer require topthink/think-view

  7. Linux系列(19) - 常用压缩命令(2)

    常用压缩格式 .tar.gz .tar.bz2 上述两个原理:先用tar进行打包,打完包再用gz或者bz2进行压缩 打包命令tar 命令格式 tar -cvf [打包文件名] [源文件1] [源文件2 ...

  8. windows10 升级并安装配置 jmeter5.3

    一.安装配置JDK Jmeter5.3依赖JDK1.8+版本,JDK安装百度搜索JAVA下载JDK,地址:https://www.oracle.com/technetwork/java/javase/ ...

  9. Laravel [1045] Access denied for user 'homestead'@'localhost' .env没有配置

    laravel 连接数据库出现错误 PDOException in Connector.php line 55:SQLSTATE[HY000] [1045] Access denied for use ...

  10. PHP ASCII 排序方法

    //自定义ascii排序function ASCII($params = array()){ if(!empty($params)){ $p = ksort($params); if($p){ $st ...