关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

云南大王-面向对象之多线程(可捎带电梯调度)

发布时间:2020-04-16 00:00:00
面向对象之多线程(可捎带电梯调度) 1. 题目重述 ​ 本题完成的任务为多部多线程可捎带调度电梯的模拟,电梯系统具有的功能为:上下行、开关门、新增一部可以使用的电梯,电梯系统在某一层开关门时间内可以上下乘客。电梯系统可以采用任一的调度策略,只要保证在一定时间内将所有乘客送至目的地即可。 ​ 本题采用的是目的选层电梯,在电梯的每层入口,都有一个输入装置,让每个乘客输入自己的目的楼层,所以一个电梯请求除了人员id,还有这个人的出发楼层和目的楼层。 ​ 电梯类型分为A型、B型、C型,在新增电梯时指定类型。初始有3部电梯,编号分别为A、B、C,新增电梯编号为X1、X2、……、Xn。三类电梯的开关门时间都分别为0.2s。 三类电梯的可停靠楼层、上升或下降一层时间、最大载客量 A型:-3, -2, -1, 1, 15~20 0.4s 6人 B型:-2, -1, 1, 2, 4~15 0.5s 7人 C型: 1, 3, 5, 7, 9, 11, 13, 15 0.6s 8人 样例输入 [1.0]X1-ADD-ELEVATOR-A [2.0]1-FROM--3-TO-2 样例输出 [2.4060]ARRIVE--1-X1 [2.8070]ARRIVE--2-X1 [3.2070]ARRIVE--3-X1 [3.2080]OPEN--3-X1 [3.2080]IN-1--3-X1 [3.6080]CLOSE--3-X1 [4.0090]ARRIVE--2-X1 [4.4100]ARRIVE--1-X1 [4.8100]ARRIVE-1-X1 [4.8100]OPEN-1-X1 [4.8100]OPEN-1-B [4.8110]OUT-1-1-X1 [4.8110]IN-1-1-B [5.2120]CLOSE-1-B [5.2120]CLOSE-1-X1 [5.7120]ARRIVE-2-B [5.7120]OPEN-2-B [5.7130]OUT-1-2-B [6.1130]CLOSE-2-B 2. 电梯调度策略 2.1 ALS调度策略 ALS电梯的请求分为主请求和被捎带请求 主请求选择规则: 如果电梯中没有乘客,将请求队列中到达时间最早的请求作为主请求 如果电梯中有乘客,将其中到达时间最早的乘客请求作为主请求 被捎带请求选择规则: 电梯的主请求存在,即主请求到该请求进入电梯时尚未完成 该请求到达请求队列的时间小于等于电梯到达该请求出发楼层关门的截止时间 电梯的运行方向和该请求的目标方向一致。即电梯主请求的目标楼层和被捎带请求的目标楼 层,两者在当前楼层的同一侧。 其他: 标准ALS电梯不会连续开关门。即开门关门一次之后,如果请求队列中还有请求,不能立即 再执行开关门操作,会先执行请求。 2.2 LOOK调度策略 2.2.1 SCAN调度策略的改进 ​ SCAN调度策略,使电梯沿一个方向进行扫描,每到达一个楼层,捎带当前楼层本电梯可以捎带(该请求的到达楼层是本电梯可停靠的楼层且电梯此时尚未满载)的请求,直至电梯到达运动方向上最远的可停靠层,再转变运动方向进行扫描。简单来说,理解为电梯在最低和最高可停靠层来回扫描,同时捎带和完成请求。 ​ 很明显,这样的调度策略很有可能会造成性能的损失,如果运动方向上没有需要捎带的请求或者电梯已无法捎带请求并且目前已在电梯内的请求需要停靠的楼层都在相反方向,则可以立刻调转方向扫描,减少来回的无效路程,这就是LOOK调度策略,具体的电梯线程实现可见下方的流程图。(有人可能会说,万一调转方向后,原先的运动方向上产生了需要捎带的请求呢?本人的观点是,这种情况的确有可能出现,但是电梯无法预知未来,所以只能选择当前情况下的最优选择,在大部分情况中,采用LOOK调度的性能要比SCAN调度好) 2.2.2 电梯线程流程图 2.2.3 换乘策略 ​ 由于本次题目的请求并不一定可以由一个电梯单独完成,所以需要让乘客进行换乘。 ​ 具体的实现方式是:在PersonRequest类的原有属性fromFloor和toFloor上增加finalFloor属性,如果该请求不需要换乘,将finalFloor赋值为0,否则将finalFloor赋值为toFloor,将toFloor赋值为中转楼层。当该请求到达中转楼层toFloor时,向调度器的请求队列中增加一个新请求,新请求的fromFloor为中转楼层、toFloor为原先的finalFloor(即该请求所要到达的最终楼层)、finalFloor为0。具体的换乘策略如下表所示: fromFloor toFloor 中转楼层 -3 2~14 1 -2、-1、2 3 1 2~14 -3 1 3 -2、-1、2 1 3 4、6、8、10、12、14 5 4、6~14 3 5 16~20 2~14 15 2~14 16~20 15 3. 多线程交互模式 3.1 生产者-消费者模式 3.1.1 模式定义 ​ 生产者(Producer)是负责产生数据的线程,消费者(Consumer)是处理数据的线程,当生产者消费者以不同的线程运行时,两者之间的速度差异会引起问题,比如消费者想要获取数据,数据还未生成;生产者想要交付数据,消费者还无法接收数据。为了解决这种生产者和消费者的强耦合问题,可以让生产者消费者通过缓冲区(Channel)进行通讯,进而消除不同线程间处理速度的差异。 ​ 通俗来说,生产者将生产的数据直接移交缓冲区,消费者直接从缓冲区中提取需要的数据,两者不直接交互。 3.1.2 模式结构 3.1.3 本题UML时序图 3.2 观察者模式 ​ 观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新,最典型的例子就是微信公众号订阅与通知系统。 ​ 微信公众号是被观察者,每一个关注公众号的用户是观察者。一旦公众号有更新(被观察者状态改变),就会向每一个关注该公众号的用户推送信息(通知观察者),然后关注此公众号的用户在微信中看到新信息(观察者状态更新)。 在观察者模式中通常会先设计观察者与被观察者的接口 观察者接口中包含update方法,用于被观察者状态更新后对观察者进行通知。 被观察者接口中包含增加观察者、移除观察者以及通知其所有观察者的方法。 设计观察者类和被观察者类实现对应的接口 在被观察者类中,需要维护一个列表用来存放其所有观察者。 通知方法通过对其所有观察者调用update方法实现通知与观察者的更新。 4. 第一次作业的血泪史 4.1 使用wait()避免暴力轮询 问题原因:消费者线程使用暴力轮询来观察是否有新的请求产生,导致CPU运行超时 惨况:在强测AC的情况下,互测中因为CPU运行超时被hack了19刀 解决方法:当请求队列中没有可以接收的请求时,使用wait()使消费者线程进入等待状态,等待notifyAll()指令唤醒线程。其实,多线程协调运行的原则就是,当条件不满足时,线程进入等待状态;当条件满足时,线程被唤醒,继续执行任务。 4.2 不是所有的同步方法都需要notifyAll() 问题原因:对于多线程同步方法的机制不清楚,在每个加了synchronized的方法中都notifyAll() 解决方法:了解多线程中线程同步的实现机制,以对象锁的同步方法为例 public synchronized void method() { // 锁住this ​ …… } // 释放锁 ​ 用synchronized修饰的方法是同步方法,锁住的对象是this,也就是调用该方法的实例,在生产者-消费者模式中,锁住的通常就是共享对象。 锁池(lock pool):假设线程A已经拥有了对象object的锁(正在调用object的某个同步方法),而线程B也试图获取object的锁(试图调用object的同步方法),但是object的锁已经被A占有,线程B就会被阻塞,进入object的锁池中等待。当线程A(执行完同步方法或执行object的wait())释放锁时,位于object锁池中的线程去竞争这把锁,竞争成功的线程则获得这把锁,竞争失败的线程则继续被阻塞在锁池中。 等待池(waiting pool):线程A调用了对象object的wait()时,线程A会释放object的锁同时A就进入object的等待池等待,当锁被释放时,等待池中的线程不会去竞争该对象的锁。当object的notifyAll()被调用后,会唤醒所有等待池中的线程,被唤醒的线程进入object的锁池中,这些线程就可以去竞争object的锁了。 ​ 在对锁池和等待池有一个清晰的了解下,可知绝大多数情况下,可以理解为该同步方法可能改变其他等待池中线程的状态(使其不再等待)时,才需要在保证线程安全的地方加上notifyAll()唤醒等待池中的线程。 5. 面向对象程序设计原则 以下内容引自课件“面向对象程序的需求分析与设计原则-1-分析与设计原则” 5.1 SOLID(经典的5个设计原则) 5.1.1 SRP(Single Responsibility Principle)——单一职责原则 ​ SRP原则,顾名思义,就是每个类或方法都只有一个明确的职责,类职责就是使用多个方法从多个方面来综合维护对象所管理的数据,方法职责就是从某个特定方面来维护对象的状态(更新、查询等)。 ​ 如果类或方法的职责过多,会导致类或方法的逻辑难以封闭,容易受到外部的影响,因外部因素的变化而变化。 5.1.2 OCP(Open Close Principle)——开闭原则 ​ OCP原则的含义是对扩展开放,对修改关闭。简单来说,当程序进行扩展增加新功能(open)时,不需要修改原有的代码(close)。OCP原则能够使程序的扩展性更好,易于维护和升级。 ​ 在使用继承实现OCP原则的过程中,需要保持好子类和父类之间的交互关系,并使用好接口和抽象类。 5.1.3 LSP(Liskov Substituion Principle)——里氏代换原则 ​ LSP原则的含义是任何父类出现的地方都可以用子类来代替,并且不会导致相应类的程序出现错误。实现OCP原则的关键步骤就是抽象化,而父类与子类的继承关系就是抽象化的具体实现,所以LSP原则是对实现抽象化的具体步骤的规范。 反例:子类虽然继承了父类的属性和方法,但子类也增加了一些新的属性和方法,可能会破坏父类存在的某些约束。比如Queue类和SortedQueue类,Queue类提供了一个返回最近一次入队列的元素,其实现方式是返回队列尾部的元素,但是SortedQueue类,会对队列中的元素进行一个排序,返回队列尾部的元素无法实现返回最近一次入队列的元素。 5.1.4 ISP(Interface Segregation Principle)——接口隔离原则 ​ ISP原则的含义是一个接口只封装一组高度内聚的操作,使用多个隔离的接口,避免封装多种可选的方案,降低类之间的耦合度。 5.1.5 DIP(Dependency Inversion Principle)——依赖倒置原则 ​ DIP原则的含义是高层次模块不应该依赖于低层次模块,应该依赖于抽象,针对接口编程。 5.2 其他重要设计原则 层次化抽象原则:程序中具有抽象层次关系(继承或实现接口等)的类在问题域中也具有同样的抽象层次关系。 均衡原则:避免出现God类和Idiot类。God类就是”无所不能“的类,各种事情都在这个类中完成,会使这个类十分臃肿;Idiot类就是”什么也干不了“,只有一两个属性和get、set方法的类。 局部化原则:类之间不要冗余存储相同的数据,方法之间不能够出现控制耦合。当类C获得了数据D后,其他类如果想获得数据D,只能向类C要。控制耦合就是直接根据传递进来的参数来决定是否要执行某个分支。 完整性原则:一个类需要提供针对相应数据进行处理的完整方法集(完整是相对于问题域需求的)。 共性抽取原则:把不同类之间具有的共性数据或处理抽象成层次关系,避免冗余。 显示表达原则:显示表达所有想要表达的数据或逻辑,不适用数组存储位置或者常量来隐含表示某个特定状态或数据。因为维护程序的人有可能会get不到这里的隐含逻辑。 信任原则:调用方法时,调用者需要检查和确保方法的基本要求能够被满足,获得调用结果后需要按照约定的多种情况分别进行处理。 懂我原则:所有类、对象、变量、方法等的命名做到“顾名思义”。不要嫌变量或方法名长(当然也不能太长),维护程序的时候一旦理解错了变量或方法的含义,得不偿失。 Tips:在许多项目中,都会使用一些约定俗成的缩写方式,比如"4"--"for","2"--"to"等,尽量避免使用只有自己看得懂的缩写。 具体的命名规范可以参考《阿里巴巴Java开发手册》。

相关阅读

计算机网络安全常见的危险因素有哪些?什么是内容分发网络(CDN)?云南服务器搭建和数据备份,恢复云南云服务器的三大作用人工智能AI初认识云计算服务的6个优势云南服务器托管有哪些注意事项Tomcat的特点云计算的三个优点选取小程序服务商时的注意事项不同数据库的不同区别什么是VPS主机它的优势是什么?你知道5G的优点和缺点吗?云南三级分销商城开发的目的和对企业的价值云南网站优化的3个方面和网页的优化我们晋级拉!!!云南网站链接维护的具体方法云南网站应该如何做优化云南网站维护的主要内容云南云服务器和虚拟主机的操作区别云服务器部署和注意点云南服务网器托管应该选择怎样的机房云南虚拟建设网站主机的优点和缺点云服务器和物理服务器的区别云服务器有哪些优势C# List用法 List介绍C#和Java有什么不同PHP的优点和缺点智慧新餐饮和传统餐饮的区别云数据库对比传统数据库有哪些优点裸金属服务器是什么它的作用是什么白盒测试的特点js中添加scriptjs中[]、{}、()的用法和区别php 字符串的整型转换ipa如何安装到苹果手机邓白氏码是什么?iOS开发者账号到期续费教程在C#中有哪些引用类型和值类型小程序搭建时需要准备些什么云数据库对比传统数据库的优势什么样的企业适合SEMjs中的常见错误C#数据类型转换字符串与数值之间的转换C#的几种循环遍历方式物联网是什么它和互联网又有什么区别?云南网站建设时应该注意些什么云计算是什么?它能干些什么?展望未来5G会给我们的生活带来哪些影响C#常见的几种报错类别C#的学习流程有哪些dedecms 绑定二级域名的正确方法SEM是什么它和SEO之间是什么关系?云南新餐饮料模式是如何运行的?云南网站建设初期应该注意哪些问题云南网站建设中原创文章对网站起什么作用Javascript中如何中断forEach循环云南零售小程序前景怎么样?如何优化WEB应用数据库访问慢的问题?Javascript中用let和var声明变量的区别是什么redis 的主从复制和哨兵?递归和迭代有何区别?<input> 标签的 readonly 属性怎么用?云南网站建设中网页版商城如何保证网站安全云南企业官网如何推广云南企业网站建设为什么把文章类型的栏目排在前面云南餐饮小程序能带给餐饮业什么?云南网站建设需要注意什么地方云南云服务器配置如何选择合适的云南网站建设和网站设计有何区别?云南网站建设—企业官网的好处在哪?云南做小程序的优势在哪?为什么建议做小程序?网站为什么要配置ssl证书?网站为什么要做seo,做seo有什么好处?微信小程序_企业付款到零钱 API 开发如何利用缓存提高asp.net网站访问速度中小型企业如何选择服务器配置?如何优化中小型企业网站C#.net做网站后台 需要记录日志基于asp.net企业门户网站设计霓裳民族服装seo优化分析建议Javascript的函数封装认识及使用Ajax请求中data与后端的交互有哪几种方法JavaScript如何实现组合模式???SQL之子查询的基本用法有哪些?什么是静态测试、动态测试、黑盒测试、白盒测试、α测试 β测试?C# 引入委托的目的是什么c# 委托的本质是什么C# DataGridView添加新行的2个方法C#支付宝扫码支付代码完整版c# MVC 微信支付教程系列之扫码支付代码实例Redis基础通用操作指令有哪些?String、StringBuffer和StringBuilder的各自用法常见的一些Dos命令有哪些?如何在C#中复制一个Windows窗体类前端js中的运算符的种类,=、==与===的有何区别?网站前端怎么设置页面禁止转载?解决XSS脚本攻击恶意代码的方法你知道?javascript 之 apply()、call() 探索net core实现跨域
/template/Home/Zkeys/PC/Static