Java实现目的选层电梯的调度
一、前言
本次博客我将简单介绍一下前两次的电梯作业,并简单解析一下我的程序结构,进一步对我的第二次作业的算法核心和一些想法做一些分享,我的电梯设计算法并不是由调度器来决定电梯的捎带与否,而是由电梯自主判断,在没有人员限制与其他条件的情况下,电梯自行判断电梯外是否有人以及是否需要捎带。
二、电梯作业的介绍
北航面向对象的课程第二单元要求设计一个载客电梯,该电梯为目的选层电梯,即需要使用电梯的人在未进入电梯时便已经输入自己要去的楼层(该种电梯已经在一些办公楼中投入使用),我们的任务是要实现它的调度算法,以实现最快最好运送完所有乘客,乘客的请求会在电梯运行过程红不断提出,我们则需要根据他们的请求控制电梯的运行,开关门,上下乘客。
三、第一、二次电梯作业的架构逻辑
简单的电梯作业不考虑电梯的最大载客量和电梯可去楼层的限制,用多线程的方法实现,是一个经典的生产者-消费者模型,可以设计一个请求池,乘客这个群体视为生产者,不断将请求放入池中,而电梯即使消费者,通过运行来满足乘客请求,视为将请求取走,因此完全是一个标准的生产者-消费者模型,因此我们创建一个Elevator电梯类作为实现电梯动作的载体,即消费者,创建一个Input类从终端接受请求,并将请求不断加入请求池中,即生产者,另外创建一个Dispatcher类,调度器,在第一次作业中调度器主要承担请求池的角色,而我们的请求池则是一个Queue队列,来存放和提供请求。
第一次作业UML类图如下:
主类中是一个死循环,不断从Input中接受请求,将请求放入Dispatcher,其中值得一提的是由于Input和Elevator都需要不断调用调度器,因此Dispatcher实现单例模式,以保证线程的安全,每一次循环创建一个接受请求的线程和执行电梯动作的线程,Operate是一个线程类,Elevator也是单例模式,接受Operate的调用,结束的标志是Input接受到null后返回一个标志表示请求结束,而后便跳出死循环结束程序
第一次作业的调度算法是傻瓜调度,即接受一个完成一个,按顺序执行请求,不存在捎带,这样的执行效率也毫无疑问是最低的,但是实现起来非常简单,不再赘述
这里值得一提的是单例模式
单例模式,毫无疑问,从名字上就可以明白即对于一个类来说在整个程序中只创建一个实例,不允许创建多个实例,每次只能调用一个实例,对于共享的资源和需要重复调用的代码块使用synchronized关键字保护起来,单例模式是多线程设计中最为基础和常见的一个模式,很好的保证了线程的安全,它的优点便是对于这种需要不安全的类实现了线程安全,但是缺点也显而易见,对于公用的代码块或共享的数据资源,如果有一个线程在用,那么其他所有线程都必须在这里等待,必须等前一个线程用完后才可继续执行,浪费了线程执行的时间;其次这样的先到先得也破坏了线程之间的优先级,如果线程并发有优先级的限制,那么毫无疑问单例模式不能胜任这样的任务,而信号量的机制,wait和notify的使用都可以解决这一问题。
第二次作业UML类图如下:
整体架构与第一次作业没有任何差别,因此不再赘述
设计思想有一些改变,首先调度器需要与电梯产生更多的交互,这要从我们的电梯说起,本次作业的电梯需要实现ALS即捎带策略,那我的想法是由电梯自行决定是否捎带,创建一个数组,对应每一楼层外的等待人数,例如如果8层有一个人按下了请求,那么floor[8]就会+1,如果这一层的人上了电梯,那么floor[8]就会-1。那么电梯每次执行都需要分两步,1.判断运行方向,运行方向有三种:向上,向下,停下,如果楼层外有人,或者电梯里有人要出来就停止运行,否则,根据电梯里所有请求的目的楼层离电梯目前楼层最近的那个楼层确定电梯向上or向下运行。2、在判断完运行方向后,如果向上或向下,那么直接输出相关信息,如果电梯停下,那么一定有人要进或者有人要出,先判断是否有人出去,遍历一下电梯中的人的目的楼层,如果有等于当前楼层的,就开门,先让要出的人出去,随后判断是否有人要进入,如果电梯外的人的请求运行方向与电梯下一步的运行方向一致,便让人进来,随后关上电梯,并且根据电梯下一步运行方向执行向上或向下操作。
优化:以上是我的设计算法,但是这样的捎带策略未必会达到时间上的最优,因为我判断电梯运行方向的方式是根据电梯里所有人的目的楼层离当前楼层最近的那一位而确定的,但是这样的算法可能会出现多次折返的情况,因此,我想如果每次按电梯里所有人中离当前楼层最远的那个楼层来确定执行方向,这样最多两次折返即可完成电梯中所有人的请求,虽然在一些小规模数据上性能并不一定优于之前的设计,甚至可能还差一点,但是不会出现那种极端的不断折返的情况,提高了电梯调度的可靠性。
四、第三次作业的任务分配算法
在讨论课上很多同学出现了A,B电梯任务繁重但是C电梯任务很轻的极大反差,请求任务的不均分配一定会降低电梯执行的效率,那么如何合理分配任务给电梯呢?我在这里提出我的一些想法:调度器中创建三个请求池,每一个请求队列对应一个电梯,这样每个电梯相互独立,只会执行自己任务队列中的任务,请求来的时候就确定加入哪一个请求队列,也就确定了任务的分配,那么如何公平分配任务呢?首先给每个任务队列对应一个变量,该变量是队列中任务个数与电梯容量的比值,即任务越多,电梯越小,那么该值就会越大,每次来一个任务时,先判断是否存在某两个电梯之间的变量值之差超过了0.5,如果是,则让任务轻的电梯接任务,如果该电梯不可以独立完成,便确定两电梯合作的汇合交接地点进而确定交接。如果没有,则判断是否可以由电梯独立完成,可以便让可以独立完成并且值相对小的电梯接任务,如果否,便确定两个合作的电梯,确定的原则还是值相对小的两个电梯合作接任务,将请求拆分分别加入两个请求队列,对请求队列中的每个请求设置有效值,只有前一个请求完成,后一个请求才有效可以执行,否则电梯会一直忽略该任务,知道该请求有效。
Java实现目的选层电梯的调度的更多相关文章
- PLC之六部十层电梯整体框架
1.基本框架 此图基于西门子杯逻辑控制赛项中电梯题目的变量表以及功能设计 1.I/O输入是指变量表中的input数字量,包括电梯所有的内呼按钮.外呼按钮.电梯平层开关等 2.逻辑处理是指根据相对应的输 ...
- .gitignore详解(附上eclipse的java项目的 .gitignore文件)
今天讲讲Git中非常重要的一个文件――.gitignore. 首先要强调一点,这个文件的完整文件名就是“.gitignore”,注意最前面有个“.”.这样没有扩展名的文件在Windows下不太好创建, ...
- 软件工程课堂练习——N层电梯只停一层求乘客爬楼层数最少(基本方法+优化方法)
题目: •石家庄铁道大学基础大楼一共有四部电梯,每层都有人上下,电梯在每层都停.信1201-1班的张一东觉得在每层都停觉得不耐烦. •由于楼层不太高,在上下课高峰期时时,电梯从一层上行,但只允许停在某 ...
- N层电梯只停一层情况下,求所有人爬楼层数最少
一.题目: 石家庄铁道大学基础教学楼一共有四部电梯,每层都有人上下,电梯在每一层都停.信1201-1班张一东每层都停有点儿不耐烦.如果在上下课高峰时刻电梯从一层上行,但只允许停留在某一层.每个人选择自 ...
- Java线程池管理及分布式Hadoop调度框架搭建
平时的开发中线程是个少不了的东西,比如tomcat里的servlet就是线程,没有线程我们如何提供多用户访问呢?不过很多刚开始接触线程的开发工程师却在这个上面吃了不少苦头. 怎么做一套简便的线程开发模 ...
- 黑马程序员:Java编程_7K面试题之银行业务调度系统
=========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== 模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 - 4号 ...
- java多线程系列1--线程实现与调度
java的重要功能之一就是内部支持多线程,这一系列文章将详细剖析java多线程的基础知识 多线程概述 多线程引入 程序只有一个执行流程,所以这样的程序就是单线程程序. 假如一个程序有多条执行流程,那么 ...
- JAVA实现DAO基本层CRUD操作
随着shh2各种操作方便框架.越来越多JAVA WEB效率,可是,假设在不了解这些框架使用的场合的情况下,一拿到项目就盲目地选择这些框架进行系统架构的搭建,就有可能造成非常多不是必需的资源浪费. 在项 ...
- java javaScript实现遮罩层 动态加载
通过java.JavaScript和css实现点击按钮后出现灰色遮罩层,并显示动态加载的字样,提高用户体验,废话不多说,上代码(写这个博客的原因是网上代码太多新手根本不知道哪里对哪里,这里剔除所有无关 ...
随机推荐
- js图片跟随鼠标移动
<div id="wrapper"><img src="http://images.cnblogs.com/cnblogs_com/rain-null/ ...
- Arcgis GDB文件地理数据库、shapefile、coverage 和其他基于文件的数据源所支持的函数的完整列表
函数 以下是文件地理数据库.shapefile.coverage 和其他基于文件的数据源所支持的函数的完整列表.个人地理数据库和 ArcSDE 地理数据库也支持这些函数,但这些数据源可能使用不同的语法 ...
- Android开发如何定制framework层服务
刚刚跨完年,新年第一篇文章,那么今天将对Android开发framework中间层的服务定制使用作个总结.首先我们先导入Android平台源码framework层的代码到开发工具eclipse中,代码 ...
- 移动端App开发 - 01 - 开篇
移动端App开发 - 01 - 开篇 从此笔记之后开启移动端 app 开发学习 该系列笔记去掉所有无关重要的东西,简介干练 我的移动端App开发笔记 1.移动端App开发 - 02 - iPhone/ ...
- IntelliJ Idea编译报错:javacTask: 源发行版 1.8 需要目标发行版 1.8
解决办法: 1.Project Settings-Modules,选择项目,选择language level 8 2.选中项目,右击选择Maven-->Reimport, 再次编译. 3.Fil ...
- python 3 输入和输出
一.普遍的输入和输出 1.输入 在python3中,函数的输入格式为:input(),能够接受一个标准输入数据,返回string类型. input() 函数是从键盘作为字符串读取数据,不论是否使用引号 ...
- (MUA)mutt-"No authenticators available" 发送不出去邮件
问题: 使用mutt发送邮件的时候,在调试模式下总是显示"No authenticators available", 后来在google上查到可能要设置验证方法gssapi,但是设 ...
- Apache的配置详解
Apache的配置由httpd.conf文件配置,因此下面的配置指令都是在httpd.conf文件中修改. 主站点的配置(基本配置) (1) 基本配置: ServerRoot "/mnt/s ...
- 为OS X增加环境变量
1.创建并以 TextEdit 的方式打开 ~/.bash_profile 文件 touch ~/.bash_profile; open -t ~/.bash_profile 2.新增环境变量 exp ...
- Java的Calendar类
通过Date类我们可以创建并格式化一个日期对象,但是如何才能设置和获取日期数据的特定部分呢?----Calendar类 Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,通过getIn ...