BUAAOO第二单元总结之电梯问题
---恢复内容开始---
Homework1 傻瓜电梯
程序架构

第一次题目非常简单,思考也非常简单,一部电梯傻瓜调度。将命令入公共的队列,电梯从公共队列中取命令即可,其中只需要使用ArrayBlockingQueue就可以使线程安全,并不需要加上锁,因为只有这个队列需要公共访问修改,使用阻塞队列即可。
同步控制
第一次作业结构简单,只需要使用ArrayBlockingQueue就可以实现同步控制。
BUG的出现
1.使用电梯取队列命令时,若也使用阻塞取,就可能使整个线程阻塞而无法退出,因此我是用poll进行取。
2.程序退出不能仅仅判定输入为NULL,还得注意命令队列是否为空,不然将导致命令还没执行完就退出。
Homework2 捎带电梯
程序架构

这一次作业对电梯的架构做了很大的调整。它与第一次是完全不同的,因为第一次过于傻瓜,其实整个电梯类并不是电梯,而是一个运算器,对from和to两个floor进行运算时间即可,本质上并不是电梯。
所以首先我得明确什么是捎带,什么是电梯,捎带就是电梯仍然就是这么去接人,只不过接人的路上可能可以捎带上别人,它的接人方向和放人方向始终没有任何变化,因此我就将电梯的属性做了很大的调整,楼层的概念变得没那么重要,而方向作为主要属性,接人方向,放人方向和接人的极限层(即从接人任务结束的那一层)作为电梯每次开始运作的基础,然后每一层再给它分配任务,而不对这三个属性做任何变化。
比起第一次的傻瓜电梯,多加了一个调度器类,同时将请求队列放在了调度器中(调度器并不是一个线程,只是一个普通类,在电梯要调用时调用)。电梯多了outelelist和inelelist两个数组,用于存储在电梯外等候的人和在电梯里的人。电梯以pick和put为一次流程,每一次流程给电梯设置pick的方向和put的方向,以及pick的楼层,然后电梯开始运行,每当运行到一个楼层(初始层也算),就给电梯分配可以捎带的任务并且加入到电梯的outelelist,并且检索outelelist是否有可以进入电梯的,有就加入inelelist(等于人进电梯),并检索inelellist检索是否有达到楼层的,有就从inelellist移除(等于人出电梯),这些操作就完成了这一层的任务,并继续运行直到pick和put结束。
同步控制
虽然第二次设计复杂了很多,但是其实被线程共享的数据只有主请求队列,而电梯内部的两个接人放人数组都是私有的,只为电梯线程使用,因此不需要控制,所以我主请求队列仍然使用阻塞队列即可。
BUG的出现
1.起初我数组遍历使用下标从小到大进行遍历并且检索到就用数组的remove,这就会导致当我remove一个元素之后使size变化而下标i继续增长,某些元素无法检索到,解决办法就是从大到小遍历。
2.在调度器每次给电梯设置pickdirection时,将正确的direction传递给电梯,然而调度器内部记录的direction没有变化,导致会增加一些不能经过的捎带任务,从而使电梯不断爬楼却无法到达捎带楼层而无限爬楼。
Homework3 捎带电梯+多部不同的电梯
程序架构



复杂度控制还行

电梯类

电梯和调度器的时序图
类的数量并没有变化,依然是电梯类,调度器类,输入类,和主类。电梯完全可以复用,只要设置上升下降速度,载客量,可停靠楼层,开关门时间就可以将多部电梯一样操作。
多部电梯和任务的关系是竞争关系,电梯去竞争任务而不是靠调度器调度任务,对调度器加锁,每次只有一部电梯可以进行调度,其他电梯就得等待。
对于载客量的限制,只要调度器每次判定电梯的总任务数量是否超过载客量(包括电梯内的和电梯外的),只要超过就不派发。
对于楼层问题,直达楼层就如作业二一样,并没有任何变化。而对于不直达楼层,我们需要对其进行分割,将其分成两个可以直达的任务,即分割第一任务和分割第二任务,这就需要解决以下几个任务:1.何时分割。我在Input类就进行了分割操作,一输入并不马上加入任务队列,而是先进行分割操作。2.如何保证先做完分割出的第一任务,再执行第二任务(即先送到中转楼层,再去接他到目的楼层,不然会造成去接但是人还没到的情况),因此我在调度器中加入了waitqueue和wastequeue,waitqueue存储的就是分割出来的第二任务,而wastequeue是电梯inelelist中被remove的元素。每次调用调度器,就检索整个wastequeue,查找其中是否有和waitqueue中相同的id(因为中转的是同一个人),有就把waitqueue中的请求加入主请求队列等待电梯竞争,没有就找下一个,并且把wastequeue的元素都清空。这样就可以保证时间的先后性,但是多次的循环检索可能会造成计算时间过长。
同步控制
新增的waitqueue和wastequeue都为多线程共享,因此我将其都调用线程安全类,使用ArrayBlockingQueue和ConcurrentHashMap两个类,保证其线程安全,同时在使用调度器的代码块加上锁,从而保证每次只有一部电梯调用调度器。这样就完成了整个同步控制流程。
BUG的出现
这次最严重的bug就是时间问题,CPU常常超出所规定的时间,原本我采用第二次作业的版式,只在电梯类的最后加入一条sleep()指令来完成暂时的休眠,然而第三次作业的调度器类太过于臃肿,其中循环检索太多使CPU运行时间过长,所以我就在每次调用调度器就notifyall并wait,并且在调度器内部也穿插了sleep,然而这就会导致另一个问题,当另外两个电梯结束线程后,就会使最后一个电梯永远停留在wait状态,于是我就使用wait(time),当wait超过time的时间就自动唤醒,从而解决了一个电梯运行的无限等待问题。
查找BUG策略
对于自身BUG查找,使用print法,在每次线程调度的开头和结尾都使用print,并且使用部分模拟数据来测试。
对于查找他人BUG,并没有很好的办法。
三次作业总结
这三次作业,让我对于多线程编程有了更加深刻的认识。它和单线程有着很大的差别,对我们的编程能力有着很大的考验,这就需要我们严谨的架构能力和对线程安全的重视。 我的架构能力确实有所提升,第二三次作业都是使用同一个架构。然而我对同步控制仍然还有很大缺陷和漏洞,我仅仅使用简单的线程安全类和一把锁,锁的范围过大也导致了某部分代码块需要运行过久时间,对notify和wait的使用也仍然生疏,这还需要多加练习。
BUAAOO第二单元总结之电梯问题的更多相关文章
- OO第二单元——多线程(电梯)
OO第二单元--多线程(电梯) 综述 第二单元的三次联系作业都写电梯,要求逐步提高,对于多线程的掌握也进一步加深.本次作业全部都给出了输入输出文件,也就避免了正则表达式判断输入输出是否合法的问题. 第 ...
- BUAAOO第二单元多线程电梯作业总结
第二单元多线程作业需要保证线程安全
- 2019年北航OO第二单元(多线程电梯任务)总结
一.三次作业总结 1. 说在前面 对于这次的这三次电梯作业,我采用了和几乎所有人都不同的架构:将每个人当作一个线程.这样做有一定的好处:它使得整个问题的建模更加自然,并且在后期人员调度变得复杂时,可以 ...
- OO第二单元作业——魔鬼电梯
简介 本单元作业分为三次 第一次作业:第一次作业要实现单部简单电梯,停靠所有楼层,无载客容量,性能分考量电梯运行时间. 第二次作业: 第二次作业实现多部电梯,电梯数量由初始化设定,每部电梯都停靠所有楼 ...
- BUAA-OO第二单元小结
一.设计策略 三次作业中,由于前两次作业都只有一部电梯,因此我的线程只有两个,一个等待队列输入进程,以及一个电梯运行进程.等待队列输入进程实现十分简单,只需要根据输入把request添加到等待队列即可 ...
- BUAAOO第二单元代码分析
第一次作业 设计思路与感想 第一次作业是要求有捎带的电梯实现, 第一次作业是花费的时间比较长的一次,花费了很多的时间去思考架构的问题.起初是想要搞三个线程的:输入线程,调度器线程和电梯线程,想要搞一个 ...
- oo第二单元——多线程魔鬼电梯
在初步认识了面向对象思想后,立刻进入了多线程的学习,本单元的难点主要是锁的理解,需要保证线程安全的同时防止死锁的发生,也要尽可能缩小锁的范围,提高性能.这一单元以电梯为载体,让我们从生活出发,从电梯运 ...
- OO第二单元总结——多线程电梯
第五次作业分析 1.设计策略 调度器采用单例模式,内部设请求队列,对请求队列的一切操作(查.增.删)都在调度器内完成,且都要求串行,从而确保线程安全.接收器和电梯是两个线程:接收器接受请求调用调度器来 ...
- 第二单元电梯调度作业 By Wazaki
figure:first-child { margin-top: -20px; } #write ol, #write ul { position: relative; } img { max-wid ...
随机推荐
- 机器学习实战(笔记)------------KNN算法
1.KNN算法 KNN算法即K-临近算法,采用测量不同特征值之间的距离的方法进行分类. 以二维情况举例: 假设一条样本含有两个特征.将这两种特征进行数值化,我们就可以假设这两种特种分别 ...
- 论文笔记:Fast Online Object Tracking and Segmentation: A Unifying Approach
Fast Online Object Tracking and Segmentation: A Unifying Approach CVPR-2019 2019-03-11 23:45:12 Pape ...
- 读书笔记--《编写高质量代码:改善Python程序的91个建议》
第一章 引论 建议写Pythonic式的代码,我理解为充分利用pythonAPI,用最简洁方式写出代码 1.两个变量交换: a, b = b, a 2.翻转list: a = [1, 2, 3, ...
- Mac 下eclipse安装Lombok插件
在官网下载最新版本的 JAR 包. 将 lombok.jar 放在eclipse安装目录下,和 eclipse.ini 文件平级的. 注意,mac操作系统下eclipse的安装路径下有两个eclips ...
- java导出excel 浏览器直接下载或者或以文件形式导出
/** * excel表格直接下载 */ public static void exportExcelByDownload(HSSFWorkbook wb,HttpServletResponse ht ...
- node中redis重连
项目node中用到redis ,做了的moudle,但是有个问题,两台redis,一台挂了,redis能自动切换,我的项目却不会自动重连: 查了资料,redis本身是实现了重连机制啊,为什么不自动重连 ...
- linux 配置ftp服务
需求:定时远程上传文件,windows->linux linux是一个云服务器,centos7 1:安装vsftpd yum install vsftpd 2:设置开机启动服务chkconfig ...
- 给Mac的Dictionary添加其他原装词典
原文:https://www.zhihu.com/question/20428599/answer/223511099 (含下载,但需要论坛注册) 下载(百度网盘):https://blog.csdn ...
- Java POJO类直接存储在MongoDB中
记录Java POJO类直接存储在MongoDB中的策略. maven: <dependency> <groupId>org.mongodb</groupId> & ...
- Mac OS X 操作系统下JDK安装与环境变量配置
1. 下载JDK. 去oracle官网的Java SE Downloads页面(如图 1),下载Mac os版本JDK(如图 2): 图 1 图 2 2. 安装JDK. 下载完成后,双击.dmg文 ...