面向对象设计入门二:多线程

一. 概述

鉴于本次作业我使用了指导书第一次要求中提出的最简单的ALS调度方式,使得三次作业的迭代过程比较简单。所以就不按照每次作业来分析,而是按照整体作业要求的模块进行分析。

二. 知识点

①    生产者消费者模型:关键在于共享资源,和共享资源提供的方法。

②    共享资源:system.in、TimeOutput也属于一种线程之间的共享资源。

③    Interrupt:isInterrupted方法在获取interrupt布尔值的时候不会改变布尔值,而interrupted方法则会改变内部真值为真。

三. 基本进程结构

  黄色代表线程,黑色代表共享资源。

  “输入结束“资源为主线程和输入线程共享,当输入线程没有结束的时候wait,如果输入线程结束则会notify主线程,使得主线程提醒创建线程输入已经结束。

  ”申请队列“资源为输入线程和创建线程共享,目的是使创建线程生成申请的电梯。

  “请求队列”资源是输入线程和各电梯共享。电梯从“请求队列”中的外部请求队列中获取请求并执行,在行进过程中从请求队列中捎带请求、返回新的转移请求。而转移请求队列的作用是:一旦电梯接取了需要转移的乘客,则该请求进入转移请求队列来表示请求没有结束,只是在转移途中。

  电梯调度器为电梯运行中分配请求、提供捎带乘客的方法。

四. 调度方式

  按照ALS调度的方式,将电梯每一次完整的运行定义为电梯主任务的运行,即:

 

  在所有箭头所示的过程中都可以捎带乘客放下乘客

五. 数据限制

  .①人数:最简单的想法,舍弃主请求未上电梯的时间,使电梯中可稍带的乘客数量小于等于最大人数-1.

  .②单层运行时间:提供给电梯使其sleep对应的时间。

  .③楼层限制:用Arraylist的enable_floor属性来保证电梯在确切的层开关门。根据A、B、C三种电梯的运行范围,1、15层是公共层。每个电梯优先接取可直达的乘客,后接取不可直达的乘客,不可直达的乘客被送到1层,同时改乘客由于还没有到达目的地,因此从1楼出发的请求会进入外部请求队列。

六. 结束方式

  首先分析三次作业电梯的停止条件:①和②:当输入线程结束,并且外部请求队列和电梯中不存在被捎带的乘客,当前主任务已经完成。③:当输入线程结束,并且外部请求队列中不存在可以接取的请求、不存在可以送达目的的请求、转移请求队列中不存在可以送达目的的请求,代表当前主任务已经完成。第三次作业时,当输入线程结束的时候,创造线程也会结束。

  通过输入结束共享资源,可以通知主线程输入线程结束。这时候主线程可以利用interrupt跳出创造线程的循环创造结构,继续通知各电梯输入线程结束并结束创造。

  当接收到interrupt的时候,电梯可能处于以下几个状态。

(1)      wait状态:等待获取一个主请求。

(2)      sleep状态:电梯运行或者开关门

(3)      正常运行状态

  (3)状态在运行一段时间后,总会进入前两种状态之一。(1)(2)状态,遇见interrupt会进入异常状态执行catch内语句。(2)总会自动结束,因此一旦抛出异常只需修改一个全局布尔变量input_end的值,修改interrupt特征布尔值后继续执行既可以了。(3)则需要等待唤醒,而且要保证一旦满足结束要求,就会立即结束。这里可以在while_wait循环中增加一个判断语句,在wait之前先判断是否已经达到了结束要求。同理也需要修改一个布尔值。

七.程序数据分析

  由于这次作业我每个class都在MainClass中,因此static行数分析基本没有参考价值。

 第一次作业:

 判断电梯是否需要开关门的方法中重复的代码较多,因为和捎带的判断基本相同;同样的问题出现在电梯run方法中。

 第二次作业:

 与第一次作业类似。

 第三次作业:

 

 与上两次作业不同,由于电梯调度器中wait部分的结束处理导致获取主请求的方法过于复杂。

 八自己debug方法以及最终出现的bug

由于多线程的特殊自行构造数据有很多的限制。因此按照讨论区的方法构造了简单的评测及,评测程序中有专门的电梯类,提供判断电梯行为的各种方法。在第三次作业中,检查到了一个判断线程结束的错误,即我才用了每个电梯分开结束的比较复杂的方式,但是当时缺少了判断”外部队列中不存在可以送达请求“这一项。

猜你喜欢

转载自www.cnblogs.com/zhaoyunqianzhuan/p/12693812.html
今日推荐