标签:支持 不同的 安全 分派 面向对象 数据 自己的 重点 运行流程
面向对象第5-7次作业总结
最近的三次作业都是有关java多线程的应用问题,而且是三个完全不同的问题,对于刚开始对多线程一无所知的状态,很难理解多线程问题的内核所在。只能是照着例子来生搬硬套。但随着对作业的不断更改和评测,也在不断加深自己对多线程的认识和了解。而且对多线程的不同线程的交互,线程安全,多线程程序的性能,多线程的随机过程等这些最重要的问题也进行了学习和掌握。
三次作业代码分析
1.多线程电梯
设计策略:
对于多线程电梯这次作业,由于是第一次接触多线程问题,所以对多线程的理解和使用还不够深刻,所以设计的时候使用了生产者和消费者的样例。对于输入队列建立单独的线程,然后三个电梯为三个消费者,在输入队列后建立三个电梯分别的队列,做为三个生产者,他们之间用三个线程安全的托盘进行交互。这样就构造了一个三生产者三消费者的设计结构。
UML图:
对于其分析来看,发现代码的圈复杂度比较高,进一步分析发现是调度器类和电梯类的复杂度比较高:
调度器对电梯请求的分类和电梯对上下行的判断结构比较复杂是导致复杂度较高的原因,但是我认为这属于比较正常的设计。这些的功能性是无法替代和简化的。
类图:
这就是输入线程producer通过托盘tray和调度器线程交互,调度器schedu通过三个托盘tray1和电梯线程customer交互。
设计不足:
由于过于依赖三个托盘,所以造成三个电梯之间信息无法准确交互,电梯内指令容易分配,但是涉及楼层指令时由于这种结构无法准确地判断指令地分配,所以出现楼层指令地混乱。
2.IFFF文件管理
设计策略:
对于此次作业,我并没有使用快照对监控目录进行不断地扫描对比,而是每当产生一个新的请求,就单独为监控文件建立对应的触发器线程对单个文件进行扫描对比。同样使用了生产消费和托盘,每次确定了监控对象后就建立一个扫描线程和处理线程,中间用线程安全的托盘进行资源共享。扫描线程不断对文件所在目录扫描,每次扫描完处理线程只针对监控文件进行对比,决定处理方式。
UML:
分析发现圈复杂度依然有点小高……
进一步确定是重命名线程的run方法的复杂度较高。我觉得是自己的判断条件较大导致的,所以对重命名线程的判断方法和处理方法应该进行简化和优化来降低圈复杂度。
类图:
输入线程确定监控对象,为每一个监控对象建立对应的四个触发器之一,触发器由两个线程组成,扫描线程和触发器对应的处理线程。Record为记录输出线程。
设计不足:
由于在设计之初指导书中并不支持对目录的监控,所以我的设计方案没有考虑对目录的监控,由于只对单独的文件进行扫描对比,所以当目录中产生新文件时因为没有对比数据所以无法对其添加新的监控。所以无法处理新文件的出现。
3.出租车调度
设计策略:
建立乘客请求队列和100个出租车线程。输入线程不断获取请求并将其加入队列中,调度器线程共享请求队列,并在请求加入队列的三秒内不断判断出租车位置并将符合条件的出租车加入此乘客的抢单名单,并在三秒后判断出租车是否接单。判断完毕后将请求从队列中删除。
UML:
对其中的复杂度进行分析:
是提供的gui程序复杂度较高,对于出租车类来说,则是因为状态转换和判断的复杂度较高,对于输入,是对乘客请求的判断和分割处理复杂度高,对于地图则是读取文件的复杂度较高。
类图:
运行流程:
二、BUG分析
1.产生bug
三次作业,第六次作业因为个人信息而无效。第五次作业产生了8个错误,这8个错误都是因为对于楼层请求的分派考虑的不够充分产生的,也是由于设计结构的不合理导致的资源共享的问题。
2.分析策略
(1)对于捎带请求进行充分的测试
(2)对于recover和监控对象为目录的情况进行重点测试
(3)对于最短路径和一辆车参与多个抢单的情况进行测试
三、心得
经过三次作业,对java的多线程问题有了更加直观和深入的理解。对于线程安全,线程交互,线程随机过程等都需要进行具体和合理的设计。简化共享对象、对共享对象的线程安全的封装等都是多线程里面非常重要的部分。而我的设计策略也在发生着变化,由最初的生产者消费者模式,到后面的简化线程由调度器线程直接进行分配调用,大大减少了线程数目,在一定程度上优化了程序的性能。
标签:支持 不同的 安全 分派 面向对象 数据 自己的 重点 运行流程
原文地址:https://www.cnblogs.com/killme7/p/8978128.html