OO面向对象多线程编程作业总结

第五次作业:多线程电梯调度

设计策略

? 在本次电梯作业当中,我构造了一个电梯请求队列线程,一个调度器线程,三个电梯线程,一个文件输出线程,还有主线程。

? 调度器扫描用户的请求队列,将每个队列分配给符合要求的电梯,每个电梯有自己的请求队列,电梯根据自己的请求队列来改变自身状态。

? 同步控制主要包含两个点:用户请求队列会被调度器和请求队列输入线程操作,需要进行同步控制,电梯内部的运行队列也会被电梯本身和调度器操作,也需要进行同步控制。

? 同步控制上,我用了synchronized关键词和wait()与notify()的方法来实现对共享资源的线程安全操作。

度量分析及类图
  • 类图:

  • 度量分析:

在类的度量分析里面,调度器类和电梯类的复杂度较高,接着分析方法的复杂度。

在调度器中,判断是否能捎带的方法复杂度较高,实际上这一部分完全可以通过模拟电梯按钮来执行,在bug分析中提到。调度电梯的方法复杂度也较高,主要是要判断电梯外的请求,分析每部电梯的累计运动量等,这里可以更加模块化一些。

电梯类的复杂度主要是方法过多,每次停在某个楼层之后都要重新计算最短的捎带请求。改变思路可以让代码简洁很多。

还有我的请求队列中的run()方法当中,我把输入的各种判断全部写在run当中了,这是很不好的习惯,应该让线程的run方法尽量简洁,把输入的操作模块化。

bug分析

这次作业我在提交之前几个小时才发现一个很重要的bug,这是我在设计思路上的一个缺陷导致的,而且指导书也没有认真阅读。在请求加入请求队列的时候,如果是电梯内的请求应该直接分配给对应的电梯,不需要等待电梯都处于能捎带或者等待服务的状态,而我却让电梯内请求等待了。最后修改的时候直接将请求强行加入到电梯队列当中,这样又导致了捎带问题。

实际上较好的设计思路应该是模拟真实的电梯,给电梯的每一层设置按钮,当有请求发送的时候,改变按钮的状态,在每一层运行的时候都判断按钮是否被按下,如果是同质请求就忽略。

还有就是线程时间的控制上面有较大的误差,不是特别精确。

发现别人的bug

这次我测试的同学的bug主要出在格式问题上面,输出的时候括号很多没有按照指导书的要求输出。

第六次作业:IFTTT文件管理系统

设计策略

本次作业中,我从主线程开启输入控制器,从输入中获取需要开启的文件监控器,监控器线程开始对文件进行实时监控,测试线程也同时开启,对文件进行修改操作,监控器检测到文件的变化,将信息发送给操作线程,对相应的文件执行相应的操作。

在同步控制方面,对文件信息的读取和修改需要进行同步操作。

还有一个stop线程是用来控制系统终止的,输入相应的指令,系统会自动退出。

度量分析及类图
  • 类图:

  • 度量分析:

在InputHandler当中,平均操作复杂度较高,因为在判断格式的方面写的代码较长,可以考虑更加模块化的判断。

各个触发器的平均操作复杂度也比较高。这也和我的设计思路有关,因为一开始没有注意到很多触发器需要监控目录下所有文件的变化,所以一开始没有对文件夹进行监控,后来增加了文件夹监控以后,代码变得冗长。

其实可以用嵌套循环单个文件监控的方式实现文件夹的监控,这样写起来会比较简洁。

bug分析&自我分析
  • bug

在测试较深的目录的时候,我的输出情况会很不稳定,比如未删除前一次的recorddetail.txt的话很容易会不稳定,线程安全的问题没有解决。

  • 自我分析

我把所有的类放在了默认的package里面,这样的架构不是很好。监控器类和操作类都可以分别放在单独的包中,监控器类也可以写成继承一个父类的方式,他们都有对文件进行监控的功能。我的程序的可拓展性和可维护性还有所欠缺。

程序比较好的地方是用了一个Operation类来对操作进行选择,每次只需要调用Operation,而不需要单独调用每个操作的方法。

发现别人的bug

对方在线程安全的设计上有所欠缺,很多文件进行了修改以后监控器可以检测到,但是并没有进行相应的操作,导致了很多输出是空。

第七次作业:出租车调度系统

设计策略

对于每一个出租车,我都开了一个线程,每一个符合要求的请求,我都会开一个调度器线程来对出租车进行调度,把符合要求的出租车加入到调度器线程的队列当中,调度器线程运行了3s以后,从队列中筛选出最合适的出租车并将请求发送给出租车执行,请求执行过程中,出租车需要被上锁,防止其他调度器线程对出租车进行调度。

度量分析及类图:

类图:

这次把不同功能模块放在了不同的package里面,information用来存储数据,taxi用来存储出租车和出租车队列,locaiton用来存储坐标和地图,scheduler用来调度,passenger用来存储请求队列,输入请求。

度量分析:

除去gui,平均复杂度最高的是taxi类,taxi的移动和状态转换的确需要很多函数来判断实现,所以不可避免的复杂度升高。

bug分析&自我分析
  • 起点终点一致的时候我没有判断错误,而是让出租车进行接单。还有出租车信息文件的输出没有实时输出。

老问题,输出的时间间隔又有误差。发现系统的sleep方法的确会产生误差,所以后面自己写了个sleep的方法进行精确的控制睡眠时间。

  • 本来这次作业想使用观察者模式,但是由于涉及的观察者类不是很多,我用了observer和notifier以后反而使代码变得十分冗杂,所以最后还是放弃了使用这种方法,感觉设计模式上还需要多加研究。
发现别人的bug

在线程调度的时间发现了问题,同时输入两条同样的请求被当做两个时间的请求,可能是中间代码出现了延迟。

在出租车自由行走以后,通过控制台输出,发现有些没有在规定时间停止一秒。

还有寻找最短路径的过程没有输出。

心得体会

1、在代码结构和设计模式上还需要多加研究,从一开始把所有类都写在一起,到后面对不同类的功能分门别类,也有了一些进步。对于接口和抽象类的使用还需要多加练习,增强程序的可维护性和可拓展性。

2、在线程的控制方面,总是会在时间的精确度上出一些问题,主要是在线程的调度方面会发生一些延迟,这些问题目前还没有找到合适的解决方案,现在能做的就是尽量简化代码的运行量。

3、感觉每次做作业之前都没有进行系统的学习就开始写代码,导致中间很多环节不会写又要到回头去学习,而且没有一个整体的框架。还是要把基础知识巩固才行。

原文地址:https://www.cnblogs.com/zackerzhuang/p/8979539.html

时间: 2024-10-01 03:47:11

OO面向对象多线程编程作业总结的相关文章

Java多线程编程作业总结

一.多线程知识总结 1.线程同步 有关创建线程的知识就不过多的叙述了.就从主要的开始讲吧,讲一下线程的同步.与操作系统中的进程同步一样,线程同样面临着资源共享的问题,怎样处理线程的资源共享是运用多线程最重要的地方.在Java中是引入锁这一概念来处理多线程之间的资源竞争的关系的."锁"的对象可以是代码块,方法,还可以是对象.一旦某一部分被锁住,我们称该部分获取了锁.那么在java多个线程中,只有拥有锁的线程才可以运行,其他线程不能运行.如果我们将竞争资源的代码块锁起来,就可以避免发生冲突

面向对象OO第5-7次作业总结

面向对象OO第5-7次作业总结 学习OO七周了,深切的感受到了这门课程的不友好.前三次作业能够算是勉强地通过了,但是从第五次作业开始就完全GG了.这三次作业,从多线程电梯开始,然后文件监控,然后到出租车,都没有写出来有效的作业.所以就不按照给定的基于度量来分析自己的程序结构了. 第五次作业 多线程电梯 这次作业是根据第三次作业改写而来的,自认为前两个电梯写的还不错,只是电梯捎带功能上少了几个判断的条件,以为这次能够加入多线程完美运行.但是实际写起来却并不如意,各个线程本身写出来了,但是在各个线程

DELPHI下多线程编程的几个思维误区(QDAC)

有几个网友私下问我一些有关线程的事情.过节写个东西上来大家交流. 思维误区1,自己新建的THREAD是线程,自己的主程序不是线程. 很多人在多线程编程没有把主线程也当作线程.其实主线程也是线程.看起来是废话,这个话确实很重要,这个就意味着,在DELPHI中,不光你开的线程,还有你的主线程所有的内存分配也是串的,进锁排队的.主线程和线程的区别 A.一般来说主线程的优先级高了点.(当然你也可以自己设置) B.主线程在WIN下是处理APPLICATION的消息. 其他基本与你自建线程无区别. 所以这一

第73课 Qt中的多线程编程

1. QThread类 (1)QThread是一个跨平台的多线程解决方案 (2)QThread以简洁易用的方式实现多线程编程 2. QThread中的关键成员函数 (1)virtual void run() :线程函数,用于定义线程功能(执行流). (2)void start():启动函数,将线程入口地址设置为run函数.启动线程,新线程开始执行run函数. (3)int exec():进入事件循环,直至调用exit().返回线程退出事件循环的返回码. (4)void terminate():强

C++面向对象多线程入门

第1节   背景 为了更好的理解多线程的概念,先对进程,线程的概念背景做一下简单介绍. 早期的计算机系统都只允许一个程序独占系统资源,一次只能执行一个程序.在大型机年代,计算能力是一种宝贵资源.对于资源拥有方来说,最好的生财之道自然是将同一资源同时租售给尽可能多的用户.最理想的情况是垄断全球计算市场.所以不难理解为何当年IBM预测“全球只要有4台计算机就够了”. 这种背景下,一个计算机能够支持多个程序并发执行的需求变得十分迫切.由此产生了进程的概念.进程在多数早期多任务操作系统中是执行工作的基本

iOS多线程编程

1. 进程,线程, 任务 进程:一个程序在运行时,系统会为其分配一个进程,用以管理他的一些资源. 线程:进程内所包含的一个或多个执行单元称为线程,线程一般情况下不持有资源,但可以使用其所在进程的资源. 任务:进程或线程中要做的事情. 在引入线程的操作系统中,通常把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位. 线程比进程更小,对其调度的开销小,能够提高系统内多个任务的并发执行程度. 一个程序至少有一个进程,一个进程至少有一个线程.一个程序就是一个进程,而一个程序中的多个任

多线程编程1-NSThread

前言 每个iOS应用程序都有个专门用来更新显示UI界面.处理用户触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验.一般的解决方案就是将那些耗时的操作放到另外一个线程中去执行,多线程编程是防止主线程堵塞,增加运行效率的最佳方法. iOS中有3种常见的多线程编程方法: 1.NSThread 这种方法需要管理线程的生命周期.同步.加锁问题,会导致一定的性能开销 2.NSOperation和NSOperationQueue 是基于OC

Python3 面向对象 高级编程

正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.  class Student(object): pass 然后,尝试给实例绑定一个属性: >>> s = Student() >>> s.name = 'Michael' # 动态给实例绑定一个属性 还可以尝试给实例绑定一个方法: >>> def set_age(self, age): # 定义一个函数作为实例方法 ...

Windows下多线程编程(一)

前言 熟练掌握Windows下的多线程编程,能够让我们编写出更规范多线程代码,避免不要的异常.Windows下的多线程编程非常复杂,但是了解一些常用的特性,已经能够满足我们普通多线程对性能及其他要求. 进程与线程 1. 进程的概念 进程就是正在运行的程序.主要包括两部分: • 一个是操作系统用来管理进程的内核对象.内核对象也是系统用来存放关于进程的统计信息的地方. • 另一个是地址空间,它包含所有可执行模块或 D L L模块的代码和数据.它还包含动态内 2. 线程的概念 线程就是描述进程的一条执