本单元的题目为设计电梯,通过这单元的学习,我初步了解了关于java多线程编程及线程之间并发安全性设计等方面的内容。以下为对这三次作业的分析与总结。

作业分析

序号

楼层

电梯数量

可停靠楼层

调度策略

1

1-15

1

1-15

任意

2

-3--1,1-16

1

-3--1,1-16

捎带

3

-3--1,1-20

3

A:-3--1,1,15-20

任意

B:-2,-1,1,2,4-15

C:1,3,5,7,9,11,13,15

 表1:三次电梯设计要求

图1.电梯设计——类与结构

一、

  第一次的电梯比较简单,楼层均为正数,一部电梯,且不限制调度策略,更重要的是不计性能分数。因此这次只需构造出读写线程,调度的时候来一个请求就执行一个请求,不需要什么算法即可实现。分析以下电梯问题不难发现这其实是一个经典的消费者——生产者模式。电梯的“按钮”(Producer)负责发出(produce)请求——调度器(Tray)收到了请求——电梯(Consumer)负责执行(consume)请求。套用该模型即可完成此次实验。

二、

  第二次的电梯稍稍麻烦了一些。首先,这次电梯引入了负层,乍一看和正层没什么区别,但在日常生活习惯上没有0层的存在,因此在地上下层切换的时候不能带入0层。其次,第二次电梯对调度策略有了要求,至少效率要达到“捎带”。我认为捎带有三层含义:第一,不能一个一个执行请求,因为捎带的时候电梯中可能有多个人;第二,要实现“捎带”。第三,要有实时的策略判断。此次的电梯仍然沿用第一次作业的生产者和消费者模式。

  负层的引入容易解决,只需要特判1<-->-1的情况,改变输出层数即可。就“捎带”算法而言,对于第一点,电梯中有多个人,显然要存储电梯里面的人的请求信息,因此我设计了一个链表来存储这些数据。

  对于第二点的“捎带”策略,捎带条件很容易理解并实现,关键在于我们需要判断“捎带”。“捎带”的判断即捎带条件,我们已经理解;那么需要在什么时候判断需要“捎带”呢?首先我想到的是来一个请求就判断符不符合判断,即“先验性”判断,但回头一想,根据电梯的实时性,在判断后可能出现其他的请求,过程难以预料且复杂多变,管理这些“先验”判断想想都让人头皮发麻,因此此路不通。而后一想,“捎带”这个动作并不是在任意的时间内发生的,只有在电梯正好到达楼层的情况下才可能出现,因此我们只需要在到达楼层的时机,判断有没有可以稍带的就行了。那么我设计了在电梯到达楼层时进行“捎带”判断,解决了这个问题。

  至于第三点,这里的实时问题的具体表现为如何一次读入所有的同时请求。此次的接口是阻塞性单个读取,显然不能一次读取多个请求,但我在这个问题的解决上花了不少时间。最后才明白,解决是不可能解决的,这辈子都不能解决,接口使然。后来捋清了思路,大概是以下的思考过程。

图2.“捎带失败”

也就是说,当送入了一个新请求后,电梯便开始判断,若发现不能捎带的话,便直接离开该楼层,导致可能会错过“捎带”。因此为了避免这种情况,当电梯有开门需求时,在中间的空闲时间内调度器可以接受指令,到了关门的时刻电梯再次询问一遍,可以保证不会漏掉“捎带”请求。但对于电梯不开门的情况,我到现在还没想出一种更为优雅的方法解决,只能在取指令的时候不断wait(),才能笨拙地解决,同时带来了时间的延迟和负载的增加。

三、

  这一次作业相当惭愧,只过了弱测,没有进入互测环节。这次失败的主要原因是对线程安全理解不到位,交上去之后先是读不到最后一条指令,之后又是CPU超时,结果就是绊倒在了中测路上。

  对于读不到最后一条指令的问题,我分析了我的代码。为了解决如二所述的漏掉“捎带”问题,我设置了一个请求缓冲类,所以说我的发送请求流程变为以下模式。

图3.输入处理

  如图所示,这样处理就会出现读不到和null用时出现的最后一条指令,因为此时缓冲类可能正在检查是否结束,发现有了end,便结束了,但是此时end前的一条指令还未送到buffer中。为了修复该问题,当时只得采用“缓兵之计”,让Button读取后sleep一段时间。在bug修复阶段,我决定不弄这些花里胡哨的东西了,所以我选择删掉这段代码(嗯,一劳永逸)。

  对于CPU超时问题,一开始是死活想不出来,检查了好几遍代码,并没有发现暴力轮询的迹象,改了几个地方,最后还是没有过。后来在BUG修复阶段,冷静下来之后,才发现自己的设计中可能存在隐形的轮询的情况——不同于易发现的循环内的暴力轮询,而是线程不断竞争形成的轮询。以下是我的作业中中发生轮询的代码。

 synchronized boolean getSignal(Elevator e) throws InterruptedException {
while (firstTrip.isEmpty() && e.isEmpty() && !isOver()) {
wait();
}
transfer(e);
notifyAll();
return dispatch(e);
}

当某个电梯获得同步后运行到此处,若不满足等待条件,就会直接运行下面的三个函数;如果该电梯不断获得同步,那么就会不断进入函数进行运算,这就增加了大量的CPU时间,导致出现了CPU超时的情况。分析自己的设计后,发现我并不需要让电梯一直请求调配,在判断是否应该阻塞时,就可以分析出电梯此时有没有任务需求。因此只需在判断条件中加入是否有该电梯需要的任务,没有的话就阻塞,防止函数“空转”,以下为修改后的函数。

 synchronized boolean getSignal(Elevator e) throws InterruptedException {
while (!adjustDir(e)) {
wait();
}
transfer(e);
notifyAll();
return dispatch(e);
}

将判断条件改为有无任务需求,将判断条件精确化,防止判断条件太过于泛化导致即便没有任务需求,也调用了函数,消耗大量CPU时间。

心得体会

  这单元主要训练了对多线程编程的理解。第一次作业目的在于让我们对多线程有个初步的了解(线程的创建、并发情况以及基础、经典的P-C模式),第二次作业在第一次的基础上对多线程的性能做了要求,第三次作业在第一和第二次作业的基础上又增加了同类线程之间的协作和通信的要求。对于多线程的心得与体会,可从线程安全和设计模式两个方面来考虑。

1. 线程安全

  线程安全问题主要针对于临界(共享)资源,即临界资源在一个时间只能由一个线程访问,这很好理解,多个线程访问的话如果进行了不同的操作,那么线程可能得到了错误的数据。对于简单的多线程模式,只需要在访问临界资源时获得同步就能保证线程安全,在这单元里,我的临界资源是调度器,电梯获得调度器的同步后,才能够调用调度器的函数。

  值得一提的是,我在bug修复阶段,电梯访问的一个调度器的函数没有加锁,如下面代码所示:

 Elevator:
public void run() {
...
while (!noTask() || ...) {
...
}
...
} Dispatcher:
boolean noTask() {
...
for (Resource r: rList) {
...
}
...
}

  rList数据的修改只能够由获得了同步的电梯进行修改,想到方法的同步是整个对象,因此后加的noTask函数就没同步,反正访问时肯定是没有其它线程占用,也是独享资源的。结果交上去出现了Java ConcurrentModificationException,for-each发生了异常。查询了关于该异常的部分知识,我发现了问题所在:虽然进入访问的时刻没有其他线程,但在访问的for-each时间内,其他线程可能进入了Dispatcher,修改了rList,从而造成异常。因此,对于多线程的临界资源,一定要进行全面的线程安全考虑。

2. 设计模式

  这个单元作业我采用了单例模式,所有的优点围绕只会实例化一个对象展开,比如这次作业的调度器,只需要一个,可以采用单例模式设计。但是由于个人的水平处于新手阶段,对编程理解并不到位,还是不太理解单例模式的优点,感觉就是实例化一个对象而已,设计工程之前,肯定会提前知道需要几个这样的对象,单例模式就显得很鸡肋。不过用了之后感觉比较省心倒是真的。

  

BUAAOO——UNIT2 SUMMARY的更多相关文章

  1. OO unit2 summary

    Unit2 一.第一次作业 1.UML 2.Sequence Diagram 3.同步块设置与锁处理 采用了生产者-消费者模式,用共享对象来连接不同的线程. 第一次作业中,我有三个线程:Receive ...

  2. Summary of Critical and Exploitable iOS Vulnerabilities in 2016

    Summary of Critical and Exploitable iOS Vulnerabilities in 2016 Author:Min (Spark) Zheng, Cererdlong ...

  3. 三个不常用的HTML元素:<details>、<summary>、<dialog>

    前面的话 HTML5不仅新增了语义型区块级元素及表单类元素,也新增了一些其他的功能性元素,这些元素由于浏览器支持等各种原因,并没有被广泛使用 文档描述 <details>主要用于描述文档或 ...

  4. [LeetCode] Summary Ranges 总结区间

    Given a sorted integer array without duplicates, return the summary of its ranges. For example, give ...

  5. Network Basic Commands Summary

    Network Basic Commands Summary set or modify hostname a)     temporary ways hostname NEW_HOSTNAME, b ...

  6. Summary - SNMP Tutorial

    30.13 Summary Network management protocols allow a manager to monitor and control routers and hosts. ...

  7. Mac Brew Install Nginx Summary

    ==> Downloading https://homebrew.bintray.com/bottles/nginx-1.10.1.el_capitan.bot################# ...

  8. Leetcode: LFU Cache && Summary of various Sets: HashSet, TreeSet, LinkedHashSet

    Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...

  9. How to add taxonomy element to a summary view?

    [re: Orchard CMS] This caused me scratching my head for days and now I can even feel it's bleeding. ...

随机推荐

  1. Docker的网络类型

    四种网络类型: None:不为容器配置任何网络功能,--net=noneContainer:与另一个运行中的容器共享Network Namespace,--net=container:containe ...

  2. 对H5新增多线程的理解与简单使用

    由于JavaScript的特性决定了JavaScript语言是一种单线程语言,但是有时候我们需要使用多线程比如进行大量的计算时.H5为此新增了多线程的方法. 在这里我是用JavaScript来实现著名 ...

  3. 吴裕雄--天生自然 python数据分析:加纳卫生设施数据分析

    import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.rea ...

  4. 吴裕雄--天生自然 python开发学习笔记:pycharm无法使用ctrl+c/v复制粘贴的问题

    在使用pycharm的时候发现不能正常使用ctrl+c/v进行复制粘贴,也无法使用tab键对大段代码进行整体缩进.后来发现是因为安装了vim插件的问题,在setting里找到vim插件,取消勾选即可解 ...

  5. 使用Google BBR加速 VPS

    0X00 预备知识 在使用Google BBR之前,我们首先要了解它是什么. 了解计算机网络的人都知道,在TCP连接中,由于需要维持连接的可靠性,引入了拥塞控制和流量管理的方法.Google BBR就 ...

  6. Vue Zero · 啟

    其实,一开始我应聘的是Spark,Hadoop这样的,然后后面呢,发现只有Java的业务给我写了,再后面我发现,公司招不到前端,所以前端要由后端来写,刺激!!! 数据驱动 首先要明白一个概念,那就是D ...

  7. Hadoop环境搭建问题总结

    最近抽空搭建了Hadoop完全分布式环境,期间遇到了很多问题,大部分问题还是可以在网上搜到的,这里说下自己遇到的两个没有找到结果的问题吧. 1.启动时报:没有那个文件或目录 原因:三台机器的用户名不一 ...

  8. Centos +Docker 安装及仓库使用概述

    ​1. Linux 系统学习Docker安装篇 这里我使用的Centos系统 安装Docker yum命令说明 即Yellowdog Update Modifier,是一种基于rpm的包管理工具 yu ...

  9. 怎么用Python写一个三体的气候模拟程序

    首先声明一下,这个所谓的三体气候模拟程序还是很简单的,没有真的3D效果或数学模型之类的,只不过是一个文字表示的模拟程序.该程序的某些地方可能不太严谨,所以也请各位多多包涵. 所谓三体气候模拟,就是将太 ...

  10. DSO 运行 —— dso_ros + Android 手机摄像头

    转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12425855.html 本文要点: dso 配置安装 dso 离线 ...