OO第二单元——多线程(电梯)
OO第二单元——多线程(电梯)
综述
第二单元的三次联系作业都写电梯,要求逐步提高,对于多线程的掌握也进一步加深。本次作业全部都给出了输入输出文件,也就避免了正则表达式判断输入输出是否合法的问题。
第一次作业——单部电梯(无调度)论述
第一次作业,是写一部电梯的模拟器,指导书提供了一个极为基础或者说不叫算法的算法,只需要将人送到正确楼层即可,对于时间、性能没有任何要求,但也是我们第一次尝试多线程,开始写代码时对于wait(),notify()函数并不是十分了解,导致出现了各种线程不安全,或是出现死锁的状况,代码写得也比较的复杂,架构并不是十分清晰。
性能分析
类
方法复杂度
明显可以看出run方法复杂度较高,其他方法为正常水平。
类复杂度
由于没有任何性能要求,我采取了接完一个人再去接另一个人的方法,效率极低,但可以保证正确性,建立了两个线程,一个Producer线程,负责读取输入,并放入共享队列中,另个一个Consumer线程,负责处理共享队列中的指令,并指导电梯上下移动,而在这次作业中我将电梯和Consumer写在了一起,也就是没有调度器线程,而只有生产者、消费者。
在后期,我也遇到了一些问题,比如结束程序的问题,我在Ctrl D后,并不能结束进程,而是卡在了一些死循环或是wait里,最终我也在用了信号量的情况下多加判断,结束进程。
第二次作业——单部电梯(ALS调度)论述
第二次作业,与第一次作业要求并无太大差别,只是增加了地下楼层,也就是负数楼层, 但在性能上有所要求,指导书给出了ALS算法,即捎带算法,在电梯运行过程中捎带路过楼层的乘客,相较于第一次作业的FAFS算法,有了很明显的进步,性能大大提高,难度也有所提高。输入输出接口仍然给好了jar文件,无需我们担心。下面先看一下IDEA对于我代码的分析。
类图

方法复杂度

复杂度较高的几个方法中都包含了较多的if条件判断,为确保正确性,只能以性能换正确。代码设计并不是十分到位。
类复杂度

第二次作业,我按照指导书使用了ALS算法,每到一个楼层,我会先让进程sleep(400),以度过开关门时间,然后检测电梯的等待队列中,是否有当前楼层的乘客在等待,若有则进入电梯乘客队列,接着遍历电梯乘客队列,将到达楼层为当前楼层的乘客送出电梯,每一次电梯运动前,都会更新一下当前的目标楼层,目标楼层也会综合考虑等待队列中的出发楼层,然后电梯根据目标楼层选择向上运动或向下运动,每运动一层为一个周期。
我认为这次作业的难点也就主要在调度一块,若是调度算法太差会导致Real-Time-Limited-Exceed,若是暴力轮询不sleep()会出现CPU-Time-Limited-Exceed,这也是我后面自己试出的一个小技巧,由于对于wait(),notify()两个方法的理解不到位,我的电梯内部采用暴力轮询,以防止错过任何一条指令或是进程在等待i队列还有指令的时候就结束。 但是我在获取指令的进程中采用了notify(),以唤醒get()方法中的wait()。
第二次作业我并不是十分成功,由于个人架构太失败,导致调度环节出问题,电梯运行方向并不会正确的改变,导致在强测时挂了多组数据,未能进入互测,这次作业我吸取了教训,知道一个不正确的架构,一定写不出一个正确的程序,在开始码代码前一定要考虑周全,想到程序运行的每一方面,尤其是结束进程方面,一定要在开始之初就设置好信号量,做好规划,而不能等到写完程序后在程序内部打补丁,强行结束程序。
第三次作业——三部电梯(自行调度)论述
第三次作业提高要求,设置为三部电梯,且每台电梯能够到达楼层互不相同,也就导致了需要乘坐两台电梯才能到达目标楼层的操作,且每台电梯运行速度,最大承载量也不相同,一开始我想使用继承,一个父类电梯包括电梯所有操作,然后用子类修改电梯的各种数据,造出三台电梯,但后来我发现了更加直接的方法,使用构造方法来确定电梯的几个参数,无需使用继承,且继承run方法我也不太确定是如何运行的。下面先看下IDEA的分析。
性能分析
类图
方法复杂度


复杂度高的函数如Tray.get(),因为三台电梯不同,导致获取的目标也不同,也就是用了if判断语句,增加了复杂度,但以后可以使用数组,传入index以减少if的使用,而在获取aimFloor一块,依然复杂度极高,毕竟有多种情况,我只能使用if判断,手动判断情况。
类复杂度

第三次作业我还是使用了生产者-消费者模式,由于会出现一台电梯无法送达的情况,我选择在当初将指令放入等待队列时,便拆分好,我会考虑所有的中转楼层,选取其中路线最短的中转楼层,然后将前一条指令先放入恰当的电梯中,后一条指令放在我的Monitor线程中,这是我新开的一个监视者线程,负责查看出电梯人员中,是否有id与监视者的等待队列中的id相同,若有,则该等待队列中的指令放入适当的电梯等待队列中,其他的架构都与第二次作业都差不多。
第三次作业的强侧表现也不太好,在这里我分享一下我debug的经历,我频繁出现CPU-Time-Limited-Exceed的问题,根据以往的经验判断,一定是暴力轮询没有sleep导致的,但我也并不是很清楚是哪一个while循环出现的暴力轮询,于是我才用输出debug的方法,在每一个while循环内部都都增加了输出,“XXX(类名):XXX(方法名) Here!”, 以判断哪一个while出现暴力轮询,当然输出结果极其恐怖,一个txt文件里面有25w+行的输出,显然找到了bug所在,但是自己在课下测试时并没有仔细测试。
这一次的经历也教会了我使用JProfiler,可以在Thread模块,查看是否有block,若是出现block,即代码内容有问题,然后使用输出debug,找到bug所在。
同时,在研讨课上,也有同学分享了System.error方法,可以输出错误数据,以后debug时可以尝试。
OO第二单元——多线程(电梯)的更多相关文章
- OO第二单元多线程电梯总结
OO第二单元多线程电梯总结 第一次作业 设计思路 Input为输入线程,负责不断读取请求并将读到的请求放入调度器中. Dispatcher为调度器,是Input线程和Elevator线程的共享对象,采 ...
- OO第二单元多线程电梯总结分析
一.概述 这一部分的作业考察的关注点与上一次的作业有所不同,上一次的考察重点主要集中在输入输出的判定以及多态的考察上面,而这一次是让我们进行多线程程序的调度与开发.这次开发过程中最大的感受就是自己之前 ...
- BUAAOO第二单元多线程电梯作业总结
第二单元多线程作业需要保证线程安全
- oo第二单元——多线程魔鬼电梯
在初步认识了面向对象思想后,立刻进入了多线程的学习,本单元的难点主要是锁的理解,需要保证线程安全的同时防止死锁的发生,也要尽可能缩小锁的范围,提高性能.这一单元以电梯为载体,让我们从生活出发,从电梯运 ...
- OO随笔之纠结的第二单元——多线程电梯
综述 主要任务就是写一个电梯模拟器,读入每一个人的请求然后让电梯把他们送到想去的地方. 从第一次到第三次作业,三次的主要任务都是相同的,但是每次都增加了很多的细节,每次的难度都逐步增长,电梯复杂度和瞎 ...
- OO第二单元总结——电梯调度问题
一.设计策略. 在三次作业中,多线程程序的实现分以下几个步骤: 1. 主线程Main类的创建多个线程. 2. 共享对象的synchronized锁保证线程之间的互斥访问. 3. 采用notifyAll ...
- OO第二单元总结——电梯
在电梯系列的作业中,笔者的整体架构几乎没有发生改变.现介绍如下,对于一个电梯系统,主要的工作步骤就是获取乘客请求.分派请求.执行请求.针对这样的工作模式,笔者设计了Elevator.Uselist两个 ...
- 电梯也能无为而治——oo第二单元作业总结
oo第二单元作业总结 一.设计策略与质量分析 第一次作业 设计策略 在第一次作业之前,我首先确定了生产者--消费者模式的大体架构,即由输入线程(可与主线程合并)充当生产者,电梯线程充当消费者,二者不直 ...
- oo第二单元作业总结
oo第二单元博客总结 在第一单元求导结束后,迎来了第二单元的多线程电梯的问题,在本单元前两次作业中个人主要应用两个线程,采用“生产者-消费者”模式和共享数据变量的方式解决问题.在第三次作业中加入多个电 ...
随机推荐
- 专项测试-App性能分析
专项测试 app性能 Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastRece ...
- Mybatis源码解析5—— 接口代理
本篇文章,可乐将为大家介绍通过接口代理的方式去执行SQL操作.话不多说,直接上图: 其实无论哪种方式,我们最终是需要找到对应的 SQL 语句,接口代理的方式就是通过 [包名.方法名] 的方式,去找到 ...
- 云真机兼容性自动化工具测试解决方案_www.alltesting.cn
问题和背景 不同类型的品牌和硬件环境.不同版本的android操作系统.IO操作系统,以及不同的分辨率,造成相同的APP在不同的设备可能存在缺陷. 兼容性测试,就是让APP.小程序.H5程序,在所有的 ...
- ldconfig与 /etc/ld.so.conf
现在我们知道了动态与静态函数库,也知道了当前的Linux大多是将函数库做成动态函数库,下面来讨论增加函数库读取性能的方法.我们知道,内存的访问速度是硬盘的好几倍,所以,如果将常用的动态函数库加载到内存 ...
- JS验证监听输入银行卡号
$("#AccountNum").keydown(function(e) { if(!isNaN(this.value.replace(/[ ]/g,""))) ...
- 华为云计算IE面试笔记-FusionSphere Openstack有哪些关键组件,各组件主要功能是什么?三种存储接入组件的差异有哪些?
1. Nova:在OpenStack环境中提供计算服务,负责计算实例(VM,云主机)生命周期的管理,包括生成.调度和回收.Nova不负责计算实例的告警上报(FC管). 2. Cinder:为计算实例提 ...
- 使用jacob调用Windows的com对象,进行word、ppt等转换成ptf、html(二)
富文本转pdf : 注意:simsun.ttc 可以百度下载:http://www.pc6.com/softview/SoftView_100415.html package com.orangecd ...
- C语言数组实现三子棋
C语言实现三子棋(通过数组) 需要包含的头文件 #include <stdio.h> #include <stdlib.h> #include <time.h> 创 ...
- C# .NET Core 3.1中使用 MongoDB.Driver 更新嵌套数组元素和关联的一些坑
C# .NET Core 3.1中使用 MongoDB.Driver 更新数组元素和关联的一些坑 前言: 由于工作的原因,使用的数据库由原来的 关系型数据库 MySQL.SQL Server 变成了 ...
- 实践node.js构建vue项目
一.首先安装下载node.js 1.Node.js 官方网站下载:https://nodejs.org/en/,自行选择合适自己的下载安装即可 2.验证安装 打开cmd,输入node –v和 npm ...


