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实现点击按钮后出现灰色遮罩层,并显示动态加载的字样,提高用户体验,废话不多说,上代码(写这个博客的原因是网上代码太多新手根本不知道哪里对哪里,这里剔除所有无关 ...
随机推荐
- css 超出部分以省略号的形式显示
想要实现文字超出部分以省略号的形式显示首先需要给此元素设置一个宽度,然后添加以下属性 overflow: hidden;/*内容超出后隐藏*/ text-overflow: ellipsis;/*超出 ...
- 我为什么用docker-compose来打包开发环境
BUILD, SHIP, RUN Docker is the world's leading software containerization platform Docker的出现,让虚拟技术更上一 ...
- Android组件化框架项目详解
简介 什么是组件化? 项目发展到一定阶段时,随着需求的增加以及频繁地变更,项目会越来越大,代码变得越来越臃肿,耦合会越来越多,开发效率也会降低,这个时候我们就需要对旧项目进行重构即模块的拆分,官方的说 ...
- 移动 App 接入 QQ 登录/分享 图文教程
移动 App 接入 QQ 登录/分享 图文教程 这里先要提两个平台,腾讯开放平台和 QQ 互联平台: (一)腾讯开放平台 官网地址:https://open.tencent.com/ 介绍:腾讯开放平 ...
- Socket for android 简单实例
最近在实现socket通信,所以写个demo来简单实现下.我用了一种是原始的socket实现,另一种是MINA框架来实现的. 下载demo:http://download.csdn.net/detai ...
- Week2——提交表单后后台的工作
在我理解看来,发生请求后主要是通过域进行相互间的协调作用的.表单数据可以从request域中获得,也可以通过response域返回数据给前台. 当发起http请求后,已经启动的Tomcat服务器解析收 ...
- python 待关注库
Python待关注库 GUI 图形 Tkinter/wxPython/PyGTK/PyQt/PySide Web框架 django/web2py/flask/bottle/tornadoweb/web ...
- laravel middleware
当你使用larvel创建一个相对比较复杂的web网站时,往往你的routes文件就会变得很庞大.一般来说在开始网站编码之前,最好做一个整体规划,把这些route逻辑上划分为不同的group,每一个gr ...
- ASP.NET Core 添加静态目录访问、使其它目录可被访问
使用app.UseFileServer 在 public void Configure(){}中,修改或添加 app.UseFileServer(new FileServerOptions() { F ...
- mysql 基础学习2
1.修改表字段顺序 在 字段增加和修改语法(ADD/CHANGE/MODIFY)中,都有一个可选项first|after column_name,这个选项可以用来修改字段在表中的位置 默认ADD增加的 ...