第一次作业

1.1 题目概述

5座楼,每座楼单电梯,类型相同,请求不跨楼层

1.2 个人处理思路



红色加粗为线程类,绿色块为临界区(共享对象)

/...鄙人还在加班加点的赶制中.qwq./

1.3 Bug记录与分析

本次强测43.99,一个bug,强测hack中了11次(挺神奇这种核心错误竟然还能过中测和部分强测),互测情况类似。

要端正测试的态度,应该说一次作业中,代码和测试应各占50%

1.3.1 个人

[1] 忘记判断elevator.isEmpty()导致电梯调度处理线程提前结束 (强测&互测)

因大体框架按实验三进行,ProcessThread结束条件亦然。后经考量,抽象出Elevator类,模拟电梯状况并记录相应原子操作,供ProcessThread操纵。

然而个人所设ELevator并非独立线程,若未判断电梯是否清空便结束ProcessThread线程,便会导致电梯内残留请求。

真是十分不爽!

明明加Elevator类时有想过这点,想着等一切成型后再来收尾,其后便忘了;清明强行赶冯如杯项目,时间不够且心生倦怠,随手测俩数据便交中测去赶OS实验了;关于测试越来越疲,侥幸心理越来越重...

总之OO状态日趋下行(学期状态也是),B屋是个警醒,今后事情还会很多,希望别再忘本。

1.3.2 他人

因为都是B屋,均有各种奇怪的bug,用“超载”“输出线程不安全”的数据共交了3次,貌似hack出了一些其他怪bug,就不细看了。

p.s.官方包输出进行线程安全的类封装

import com.oocourse.TimableOutput;

public class SecureTimableOutput {
public static synchronized void println(String str) {
TimableOutput.println(str);
}
}

第二次作业

周五下午才开始想,发觉要加的东西还挺多,晚上开写时整个人如坐针毡感觉大难临头。于是不经思索的加类,继承/复用什么的就不管了,代码开始向一坨shi发展。好在Elevator相关模型进行了一定的泛化,想清楚后修改不多,的亏上一次的设计了。

多线程学得挺差,到现在最理解的也就只有synchronized一个method,ReentrantLock还没用过。我们似乎没法直接指定一个线程中某几行代码为原子操作,运行期间不切换线程,只能间接通过设置一些临界区并加锁来实现局限视角下的原子性,得处心积虑地控制且无法完全掌控,真挺难受。

最后幸好赶在周六中午完成,但慌忙之间很多东西没有细细琢磨;最后优化了一下午的代码反而又出现运行线程关不掉的事情,git部分文件版本回退操纵不熟悉,心烦意乱就交了没有任何调度策略的初版。但凡我提前一天晚上开始写也不至于这么狼狈了。

2.1 题目概述

  • 5座楼,每座初始单电梯,在同楼座中上下跨楼层运动,可在运行时通过请求指令加楼座电梯
  • 10层楼,每层初始无电梯,在同层中左右跨楼座运行,可在运行时通过请求指令加楼层电梯
  • 乘客请求不会既跨楼座也跨楼层

2.2 个人处理思路

/...鄙人还在加班加点的赶制中.qwq./

2.3 Bug记录与分析

本次强测91.84,强测互测没被hack出,可谓谢天谢地。

改进版出了问题没时间修bug,交了使用随机调度策略的初版,自然没有性能,下次注意。

一直没空写测评机啊,感觉是很大一块缺失。

2.3.1 个人

[1] 楼层调度线程的开关问题

个人处理时一开始没看清楼层电梯初始不存在,于是Main中直接把楼层调度类(FloorProcessThread类)线程打开了。这样的话,在其下的电梯列表为0时,应该进入wait状态,直到共享的电梯列表类(ElevatorThreadQueue,别问为啥写Queue,为了和PersonRequestQueue对称防止看错)加入电梯或总体分配类线程(ScheduleThread)结束

[2] 优化调度策略+一些其他修改后,运行过的电梯调度线程+电梯线程关不掉

我所谓的优化,便是将一次调度将一定数量的同向&顺路请求交给同一电梯,电梯找当下最远请求,便能在路上最大捎带。

而bug原因在于,从getNearestRequest()改为getFarthestRequest()时,max初值设为了0(当时想着楼层没有0,肯定取不到,笑死怎么回事),然而电梯和请求在同层时相对位置就是0,所以导致请求队列有请求而取不出,异常循环停不下来了

giao!

[3] 同样是改为getFarthestRequest后带来的bug

原因在于arriveTo()方法运行步骤有缺陷,该缺陷可与getNearestRequest()适配,而不与getFarthestRequest()适配。

之前的arriveTo(int to)

  • 若to和当前电梯位置重合,则当前若elevator.hasOut() || hasIn(null),进行一次出入
  • 若to和当前电梯位置不同,则向to的方向移动。循环过程:
    • while(to和当前电梯位置不同) {移动一层 -> 若elevator.hasOut() || hasIn(orient),则进行一次出入}

问题手

上述ariveTo()搭配getFarthestRequest()

35-FROM-B-1-TO-B-4
47-FROM-B-10-TO-B-7

开局主请求为47-FROM-B-10-TO-B-7,所以直接移动,不会捎带35;运行到10层时退出循环,主请求未进入电梯,结束当前主请求;

然后主请求变为35-FROM-B-1-TO-B-4,47同样未进入电梯(若为getNearestRequest(),则此时主请求为47-FROM-B-10-TO-B-7,然后将其装入电梯),直接向1层运行;

如此循环往复

修正

修改一下arriveTo()中的运行逻辑:

//get step (orient)
while (curPos != to) {
executeInOut(step);
elevator.move(step);
curPos = to < 65 ? elevator.getFloor() : elevator.getBuilding();
}
executeInOut(null);

2.3.2 他人

没啥空,感觉互测要想有所收获,付出的成本(好好读代码)挺高,权衡了下收益这次就没hack人。

[1] 增设电梯请求后没有乘客请求,导致线程未关闭

别人那儿看来的一个hack数据,感觉挺不错。估摸就是如标题描述,wait后没有notify起来

第三次作业

虽说想提早写,但最后还是周五开始的(下午基物实验,结果和上周差不都多)。一问周围同学好像大都周五前不会动作业,似乎就安心了很多。。。

既然当初没有选择自由竞争,也没太多时间想了,那就调度到底吧。从来没有那么感谢过多态,迭代过程出奇的舒服。

3.1 题目概述

  • 5座楼,每座初始单电梯,在同楼座中上下跨楼层运动,可在运行时通过请求指令加楼座电梯
  • 10层楼,初始1楼有一全座可达单电梯,在同楼层左右跨楼座运动,可在运动是通过请求指令加楼层电梯
  • 乘客请求可能既跨楼座又跨楼层,所以要考虑换成
  • 楼层电梯追加可达区域,所以分配时要增加判断

其余新增可定制电梯人数、运行速度等不足道

3.2 个人处理思路

继承原请求类构造新类——多阶段请求类

/...鄙人还在加班加点的赶制中.qwq./

3.3 Bug记录与分析

本次强测82.75,被hack3个点,再进B屋。无可抱怨(),是我楼座调度欠考虑。互测因为相同的问题被hack两个点

只写了数据生成器(这个容易),输出数据正确性判断似乎十分的纷繁复杂,在时间和兴趣不太够的情况下,知难而退了,导致个人测评姬流产。

3.3.1 个人

[1] 若是本身请求仅跨楼层,则stage=2运载结束时即可完成请求

此类思维疏忽,靠测试查出。但这种bug的多少,也衡量出一个程序员水平的高低吧。。。

[2] 改为流水线模式后可能引发的忙等情况

因为迭代为流水线模式,设置了TransferCounter的单例模式记录正在中间运输处理的请求。ScheduleThread线程结束的条件改为waitQueue.isEmpty() && waitQueue.isEnd() && TransferCounter.getInstance().isEnd()

waitQueue为空而TransferCounter并没有setEnd,则线程不会退出。继续运行至waitQueue.getOneRequest()时,会拿到锁并因为队列空而进入等待。此时尚有完成阶段任务的请求想要重新加入waitQueue,进入忙等。

解决:将waitQueue共享给TransferCounter在完成阶段任务后TransferCounter.getInstance().release()中加入waitQueue.notifyAll()以唤醒线程结束忙等。

[3] 楼层调度策略的可达性判断有误(强测&互测)

我在ScheduleThread中设置了accessMap[11]记录每个楼层在当前加入的电梯下可达的楼座,然而记录的方式却是将所有楼层电梯的mask全部或起来。这种方式的错误在于两条路径覆盖的点集中,未必两两结点可达

例如:5楼横向电梯中,电梯1可达A、C,电梯2可达B、D,此时请求A->B显然不能被此时的5楼电梯处理。然而我设计的调度器会因为accessMap中ABCD的mask都在,将该请求放入5楼请求队列中,而此时5楼队列无电梯可接送,所以就忙等了。

解决:静态的调度,所以就将accessMap改成ArrayList<HashSet<Integer>>,记录每个加入电梯的mask依次比较再决定调度。似乎挺没技巧但改动最小。

他人

由于流产的测评姬,测试一事显得极为麻烦。又是无hack的一周。。

总结

4.1 关于同步块的设置和锁的选择

同步块和锁均用在了共享对象里,正如前文所述,利用对共享对象加锁间接操纵线程的运行顺序。

实现:对共享对象进行了类的封装,在类的方法中使用synchronize关键字加锁,并在有线程调用竞争的synchronized方法结束时进行notifyAll()

4.2 调度器设计

调度器其实就是执行请求分配相关操作的一个线程类。

  • 第一次作业仅有的调度器为,将请求从watiQueue分配到每座楼的processQueue。(ProcessThread为电梯的一部分-策略部分,不是调度器)
  • 第二次作业采用传统的调度策略,所以正式出现两级调度器:
    • ①ScheduleThread: 将waitQueue分配到各楼层/楼座的processQueue
    • ②BuildingProcessThread/FloorProcessThread: 将processQueue分配到相应可运载的电梯中elevators(elevators的元素为整个ElevatorThread,是为了拓展优化调度算法时方便获取电梯信息)
  • 第三次作业同第二次作业,只不过将一级调度器ScheduleThread变为单例模式

没有好好比较自由竞争和调度器的各自状况

4.3 心得体会

再一次深刻体会到计算机相关行业的价值观——结果导向。没有正确产出的代码,怎么样都像是耍流氓。我们通过黑箱测试找bug,社会也通过黑箱筛选我们。很残酷,却也在理。个人历程的色彩及意义,封闭在以个人命名的对象中,社会的调用只需你满足相应的接口设计即可,两不相干,才能高效调度。

突然有些恐慌,对于受人之托的程序员来说,自己在写在培育的代码,其意义来源却是他人的需求。被别人召之即来挥之即去的,是我们的心血,这多么可悲。倘若想能为自己而写代码,目前的水平下没多少出路。

多线程整个单元的作业都做得比较急,没有思索和额外拓展,所学仅为代码所写的内容,着实不够。不过在层次化设计方面,切切实实的体会到了多态的好处(说:谢谢多态!),使思路清晰工作量大减。

测试方面,感觉测评姬的搭建要比第一单元难了不少,而没有测评姬辅助,靠人力很难进行自我强测检验,互测时同样困难(看别人代码过于痛苦)。课程组是不是可以提供些许测评姬搭建的台阶呢。

同时,中测数据点设置的过于弱导致强测翻车的话,分数很难看且感觉不算太公平(承认,很大部分是自己测试的原因),是否可增强一些中测数据点,比如强测数据点普遍涉及的数据特征应该在中测中有所体现,以防强测大量hack同质bug。

最后,其实看DS、CO、OO、OS,在得分上真正掣肘人的地方不在知识本身而在于debug能力上。都说向死而生,鉴于本人写bug能力,便应时刻“向bug而写”,也为debug设伏。

【Unit2】电梯调度(多线程设计)-作业总结的更多相关文章

  1. OO第二次博客作业——电梯调度

    OO第二次博客作业——电梯调度 前言 最近三周,OO课程进入多线程学习阶段,主要通过三次电梯调度作业来学习.从单部电梯的傻瓜式调度到有性能要求的调度到多部电梯的调度,难度逐渐提升,对同学们的要求逐渐变 ...

  2. OO第二单元总结(多线程的电梯调度)

    经过第一单元作业的训练,在做第二单元的作业的时候,要更加的有条理.但是第二次作业多线程的运行,带来了更多的运行的不确定性.呈现出来就是程序会出现由于线程安全问题带来的不可复现的bug.本单元的作业也让 ...

  3. OO Unit 2 电梯调度

    目录 OO Unit2 博客作业 基于度量来分析⾃己的程序结构 复杂度分析 架构分析 改进和重构 发现过的BUG 简化问题 多线程初探 OO Unit2 博客作业 基于度量来分析⾃己的程序结构 自认为 ...

  4. 电梯调度编写(oo-java编程)

    第二单元的问题是写一个关于电梯调度的程序. 需要模拟一个多线程实时电梯系统,从标准输入中输入请求信息,程序进行接收和处理,模拟电梯运行,将必要的运行信息通过输出接口进行输出. 主要锻炼学生的多线程程序 ...

  5. OO第二单元电梯线程系列总结作业

    电梯系列第一次作业 功能描述: 傻瓜电梯无需考虑超载捎带 线程模式: Producer-Consumer Pattern 思路: 第一次作业是一个傻瓜电梯,分别有一个生产者生成电梯指令(也就是Inpu ...

  6. OO电梯调度

    告别了三次奇妙无比的求导作业之后,我们就开始搭建一部自己的电梯了.相信我们不同同学的电梯运行方式肯定各具特色吧,但值得肯定的是,在艰苦的走完了三次电梯逐步改进的作业之后,我们的电梯在正常情况下应该是可 ...

  7. Java多线程编程作业总结

    一.多线程知识总结 1.线程同步 有关创建线程的知识就不过多的叙述了.就从主要的开始讲吧,讲一下线程的同步.与操作系统中的进程同步一样,线程同样面临着资源共享的问题,怎样处理线程的资源共享是运用多线程 ...

  8. OO面向对象多线程编程作业总结

    第五次作业:多线程电梯调度 设计策略 ​ 在本次电梯作业当中,我构造了一个电梯请求队列线程,一个调度器线程,三个电梯线程,一个文件输出线程,还有主线程. ​ 调度器扫描用户的请求队列,将每个队列分配给 ...

  9. 第二单元总结:基于synchronize锁的简单多线程设计

    单元统一的多线程设计策略 类的设计 电梯 每部电梯为一个线程. 电梯从调度器接收原子指令,知晓自己的状态(内部的人/服务的人.运行方向.所在楼层) 原子指令包括且仅包括: 向上走一层 / 向下走一层 ...

  10. 北航OO第二单元——电梯调度

    三次作业要求简介 特点:目的选层电梯 在电梯的每层入口,都有一个输入装置,让每个乘客输入自己的目的楼层.电梯基于这样的一个目的地选择系统进行调度,将乘客运送到指定的目标楼层. 第一次: 在任意时刻输入 ...

随机推荐

  1. Nginx日志重定向到标准输出

    背景静态站点使用`docker`部署时,希望`nginx前台启动`的同时可以将错误日志和访问日志全部重定向到标准输出,便于采集和处理! 实现只需要修改`nginx.conf`中`3行`关于日志的配置就 ...

  2. Qt编写地图综合应用11-动态添加

    一.前言 在添加设备点或者区域形状的时候,会考虑是直接静态的方式写入到网页中加载,还是动态js函数异步加载的方式,这个需要根据现场的实际需求来,如果只需要一次加载的话建议静态即可,如果运行期间还需要动 ...

  3. 即时通讯技术文集(第31期):IM开发综合技术合集(Part4) [共13篇]

    为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第31 期. ​[- 1 -] IM消息ID技术专题(一):微信的海量IM聊天消息序列号生成实践 ...

  4. 融云技术分享:基于WebRTC的实时音视频首帧显示时间优化实践

    本文由融云技术团队原创投稿,作者是融云WebRTC高级工程师苏道,转载请注明出处. 1.引言 在一个典型的IM应用里,使用实时音视频聊天功能时,视频首帧的显示,是一项很重要的用户体验指标. 本文主要通 ...

  5. IM开发干货分享:浅谈IM系统中离线消息、历史消息的最佳实践

    本文由融云技术团队原创分享,原题"IM 消息数据存储结构设计",内容有修订. 1.引言 在如今的移动互联网时代,IM类产品已是我们生活中不可或缺的组成部分.像微信.钉钉.QQ等是典 ...

  6. 记录小程序跳转h5,然后h5涉及下载文件的问题

    小程序跳转h5中,可以在小程序增加一个页面使用webView方式嵌套三方小程序,不过需要配置白名单 由于小程序的限制,不能在嵌套的h5中进行文件下载 网上也没有很好的解决方法,解决方法是再跳到小程序带 ...

  7. Solution Set - “卷起击碎定论的漩涡”

    目录 0.「CF 1788F」XOR, Tree, and Queries 1.「CF 1815F」OH NO1 (-2-3-4) 2.「CF 1787F」Inverse Transformation ...

  8. 让 LLM 来评判 | 基础概念

    基础概念 这是 让 LLM 来评判 系列文章的第一篇,敬请关注系列文章: 基础概念 选择 LLM 评估模型 设计你自己的评估 prompt 评估你的评估结果 奖励模型相关内容 技巧与提示 什么是评估模 ...

  9. python基础学习4

    打开文件的方式 # 第一种 f = open('C:\project\pycharmprojects\\bigdata33\day05/cars.csv', mode='r', encoding='U ...

  10. [转载] ABP框架理论学习之后台工作(Jobs)和后台工作者(Workers)

    介绍 ABP提供了后台工作和后台工作者,它们会在应用程序的后台线程中执行一些任务. 后台工作 后台工作以队列和持续的方式在后台给一些即将被执行的任务排队.你可能因为某些原因需要后台工作,比如: 执行长 ...