第五次作业
- 作业简介
第五次作业内容为模拟同一栋楼三部电梯的协同工作。模拟作业对乘客请求做出判断并按照一定算法将请求分配到具体的电梯上执行。
- 设计思路
这一次作业在第三次作业的基础上增加了多部电梯的协同工作。由于每一部电梯的状态和运动相互独立,采用多线程设计很有必要。我的思路是将三部电梯分别对应一个线程,来描述这三部电梯的运动;将请求输入作为一个线程来不断地获取用户请求;将调度器作为一个线程,及时将获取到的请求分配到具体的电梯上。程序类图如下:
由于第一次接触多线程编程,这套电梯系统对我来说难度不小。楼层请求的分配处理对于多线程的协同要求很高,这也是此次作业最大的一个难点。从类图上看,程序基本符合设计思路,将输入、调度器、电梯分别作为线程类。
- 度量分析
最终我的程序结构如下图:
从度量分析结果可以看到,我的主要的三个类中都有一个方法复杂度较高,而且三个方法都用于实现该类的主要功能。也就是说我习惯于将类中的主要功能集中于一个方法上,虽然相对于前几次作业来说有所改善,但仍需将功能细化,将各个方法分工明确。总体代码规模也比较大,说明程序不够简洁。
- 时序图
- Bug分析
由于在设计多线程操作时对捎带请求考虑不周,我的程序在处理某些不满足捎带的请求时会产生捎带现象,导致了一个严重的Bug;此次互测中对方的代码思路比较严谨,我并没有对方的发现任何Bug。
第六次作业
- 作业简介
第六次作业是一次IFTTT工作,内容为对单个文件或目录下所有文件的监控,监控文件的重命名、修改大小、修改最后修改时间、修改路径四种操作,并对应进行统计触发次数、保存修改信息和recover操作。
- 设计思路
根据指导书对这一次作业的要求,我将针对每一个监控对象的一个触发器设置为一个线程。只要监控对象触发了触发器,这一个线程可以执行一个或多个任务。本次多线程的冲突集中在文件资源的竞争上,所以设计一个线程安全的文件操作类就能够很好地解决多线程同步问题。在程序类图如下:
在设计了线程安全类SafeFile类后剩下的工作就是算法的设计了。经过了上一次作业对多线程的理解,这一次我在对线程冲突的处理上好了一些。
- 度量分析
最终我的程序结构如下图:
从度量分析结果可以看到,每个方法的整体复杂度还算比较低,不过我的方法数量很多,其中存在的一个问题是某些方法的相似度比较高,我认为可以做适当合并来提高代码的可读性并保持良好的逻辑结构,这是后续值得优化的部分。此外,有几个方法的逻辑嵌套深度较大,可适当优化逻辑判断。
- 时序图
- Bug分析
本次作业存在一个Bug:当前监控目录存在多个属性相同的不同名文件时。这些文件的其中一个重命名会导致另外的文件重命名触发器的触发。属于逻辑判断上存在的Bug。此次互测对方存在严重错误,无法对目录进行监控,对文件的监控也存在很多问题。
第七次作业
- 作业简介
第七次作业是模拟出租车系统工作。在80*80的矩阵网格地图上随机放置100辆出租车,对于任何时刻的乘客叫车请求,系统给予相应的回应。
- 设计思路
-
与系统有交互关系的对象识别
-
特征分析
用户交互的数据特征:提供乘客当前坐标和目的地坐标、乘客标识符。
用户交互的时间特征:用户输入乘客请求时以当前的系统时间作为请求时间。请求在系统单位时间(100ms)内算作同时的请求。
地图数据特征:地图数据固定不变,提供相邻结点之间的连接情况。
地图时间特征:不随时间改变而变化。
-
对象识别与构造
地图类Map:
地图类的作用为读入并保存地图信息,提供地图中每两个点之间的最短路径。
用户类User:
用户类的作用为从控制台不断读入用户从控制台输入的请求,并将用户的请求传递。由于需要一直监控控制台输入,所以该类应为一个线程类。
请求类Request:
请求类是一个数据类,记录乘客请求的所有信息。
出租车类Taxi:
出租车类表示出租车的坐标位置,以及运动状态(等待服务状态,接单状态,停止状态)。出租车行驶一条格子边需要200ms。出租车无论在什么状态下都是独立运行,所以出租车类应为线程类
输出类Output:
输出类负责所有输出内容,包括控制台响应输出和将处理过程输出到文件。
类方法:几个静态方法,按照条件输出即可
分配类assign:
分配类是一个线程类,该线程启动3s并在启动时间内将进入以请求为中心的4x4范围内的出租车纳入抢单列表,并在最后结束时选择一辆出租车派单
程序类图如下:
- 度量分析
最终我的程序结构如下图:
从度量分析结果可以看到,除了提供的GUI类以外,部分方法的复杂度和嵌套深度较高,需要优化。
- 时序图
- Bug分析
本次作业存在一个输入格式限制的Bug,除此之外目前没有发现Bug。此次互测对方有一个输出时间上的争议,目前仍在沟通确认。
总结
通过这三次作业的练习,我对多线程的理解从零开始日渐加深,也体会到多线程的强大之处。然而多线程编程中的难点就是处理共享资源以及线程之间的交互。这其中有很多技巧是需要在不断地实践练习中掌握的。希望在以后的编程实践中能够对多线程问题有更加深入的理解和掌握。