OO fifth, sixth and seventh homework summary

 

1. Thread coordination and synchronization control strategy

 

fifth assignment

 

       In this job, there are three types of threads in the above figure, namely scan thread, scheduler thread and elevator thread. The request queue is shared between Scanner and Scheduler, and the sub-queue and lamp object of three elevators are shared between Scheduler and three elevators. . Therefore, the implementation of thread synchronization starts from the shared object. When the scheduler finds that the queue is empty, wait, otherwise, it keeps scanning the queue. Every time the Scanner scans a valid request, it will be added to the queue and notified, so that the two are synchronized through the public queue. . Between the scheduler and the elevator, the public light object and the sub-queues of the three elevators, but I chose to lock the elevator during the implementation. After the scheduler obtains the elevator's lock, it can add the request to the elevator's sub-queue, the elevator The condition for releasing its own lock is that the elevator is in the running state (this.wait(3000) is executed every time the elevator goes up a floor), in addition, when the state of the light object is obtained (when judging homogeneity) and the elevator reaches a floor, it needs to be The first thing to do when turning off the corresponding light is to obtain the lock for the light.

 

sixth assignment

 

       The specific implementation idea of ​​this job is to first read the monitoring tasks at one time, filter out the repeated and invalid task instructions, and then start a monitoring thread for each task. The corresponding HashMap is used as a private attribute of each monitoring thread. The Key of the HashMap is the absolute path of the file, and the Value is a data encapsulation object, including the file name, size, and last modification time. Compare with the old HashMap, check whether the trigger condition is met, and then execute the corresponding task. The thread safety of this job mainly lies in the two data storage objects Detail and Summary. In this job, my strategy for implementing thread synchronization is to lock the two data record objects, Detail and Summary. When the monitor meets the trigger condition and the task is When RecordDetail or RecordSummary, when the monitor records data to Detail or Summary, it needs to obtain the lock of Detail or Summary first. In addition, Detail or Summary also needs to obtain its own lock when regularly outputting the record content to the file, so Since then, thread synchronization and data safety can be achieved.

 

The seventh homework

 

       The idea of ​​​​this job is to first build a static Map class to contain map information, and BFS static methods to find the shortest path. When the program starts to run, the Map must be initialized first, and then the main threads, including instruction scanning threads, taxis, should be started. The management thread and the monitoring thread that starts for 3s for each specific instruction. The scanning thread shares an instruction queue with the Controller. When the instruction queue is empty, the Controller waits and executes the notify method every time the Scanner scans the code for a valid instruction. , the thread synchronization between the two is relatively simple. The Controller opens a 3s monitoring thread for each request. When the 3s monitoring time ends, the Monitor adds the corresponding request to the corresponding taxi. At this time, the corresponding taxi needs to be obtained. Lock. Regarding the realization of the running mode of taxis, I did not design each taxi as a thread but as an object similar to a finite state machine, and the state change came from the refresh signal of the taxi management thread (analogous to the time rise in the group experiment along), the taxi management thread is only responsible for providing a refresh signal to 100 taxis in the taxi queue every 0.2s. Please refer to the following figure for the update of taxi status. Only the Monitor object (that is, the behavior of dispatching the order) can modify the data of the taxi. Because the method executed when the order is dispatched (the condition is that the target taxi is in the WFS state and is the optimal taxi) will immediately modify the corresponding taxi's data. The state is GFS, and this method can be placed in the synchronization block to achieve thread synchronization and avoid the phenomenon of different monitors dispatching orders to a taxi at the same time.

 

 

Second, the program structure analysis

 

fifth assignment

 

Metrics measurement results:

Class Diagram:

 

 

 

 Program analysis: The advantage of this design method for this operation is that the idea is relatively simple and clear. The above synchronous control method ensures that the elevator's own one-time dispatch (judging the piggyback and the next main command and other operations) will never be disturbed by any outside world. , the disadvantage is that the amount of code in the synchronization block is large and the running time is long. If the simulation time is not used, the time error will become larger and larger. Since a large part of the design ideas and implementation methods of this operation are inherited from the previous two elevator operations, so The implementation of thread synchronization is subject to this to a certain extent. In addition, the code style is still a bit poor, the nesting depth of the code is too deep, and the cyclomatic complexity is also high. In terms of design principles, the main problem is the DIP principle. The code is too detail-oriented and cannot be abstracted enough, and the reuse principle is relatively poor.

 

sixth assignment

 

Metrics measurement results:

 

 

Class Diagram:

Program analysis: For the specific implementation of this job, the advantages are that the control structure and job flow of the program are clear and clear, the thread synchronization is much better than the previous job, and no excessive delay or deadlock phenomenon has been found. In this work, HashMap is used to manage the file directory, which makes the comparison and search much more convenient. Regarding the shortcomings, no problem has been found in thread synchronization. The main problem is still in the design principle. The code is oriented towards Details. The problem is serious, and the commonality cannot be extracted and then raised to the abstract level. Although it has nothing to do with correctness, this design habit will cause the code to be inconsistent. Readability and maintainability have become very low. In future operations, we should take this shortcoming seriously and improve it. For incremental jobs, such shortcomings may be gradually enlarged and finally affect the correctness. Multi-threaded elevator This problem occurs at work.

 

The seventh homework

 

Metrics measurement results:

 

Class Diagram:

程序分析:本次作业中我采用了1*100的设计而不是100*1(具体参见第一部分),这样做的优点是出租车的刷新动作几乎是同时的在GUI上显现的比较明显,几乎无延时出租车位置同时变更,在线程安全方面也减少了很多问题几乎不存在线程安全隐患,缺点是可能这样做可能有点违背了模拟的本意,有一点取巧的意味。在本次的Metrics度量结果中可以看到,抽象问题相较于前两次作业有所改善,但是嵌套深度问题依然存在,在这一点还需改进。设计原则方面,本次作业被报了一个懂我原则方面的缺陷,在类、属性的命名方面,做的确实不够好后续作业中要做到顾名思义,少偷懒。

 

三、BUG分析

 

第五次作业

       本次作业被发现一个bug,这个bug来源于线程同步做的不好,加了太多的synchronized锁导致时间误差越积越大,最后导致正确性的问题。究其原因是在电梯对象上加锁的选择导致同步块中包含进了大量的无需同步的代码,导致其他线程等待时间变长,误差越积越大影响正确性。

 

第六次作业

       本次作业被发现一个bug,这个bug是公测bug,具体是监控目录的时候对Renamed文件进行Recover操作时又会触发自己的Renamed触发器,导致文件名在两个名字之间跳来跳去。究其原因,是执行Recover的时候忘记再一次更新快照,导致快照存储的是未Recover之前的结果这样下一次扫描又会触发,又会把文件名改回去如此反复。

 

第七次作业

        本次作业被发现一个bug,bug产生的原因是当出租车接单时正好位于乘客处此时BFS的结果为空,但是出租车运行时是在一个路径队列中每次取队头元素作为下一个位置的,又因为此时队列为空,就导致取队头元素时产生了Crash错误。

 

四、寻找bug的策略

 

1、结合bug树分点测试寻找bug

2、阅读代码,寻找逻辑漏洞或者存在线程安全隐患的地方

3、由于多线程程序具有随机性,有的问题在一次测试中可能体现不出来或者不明显,故可以使用较多较大的测试数据随机轰炸

4、构造测试数据对边界情况进行测试

 

五、心得与体会

 

1、为了保证正确性而一味地增加同步部分实质上是把bug转移到了别的地方,回头看自己加锁同步的部分发现很多是不必要的,冗余的同步操作最终会体现在正确性上,在保证安全的前提下应该尽量减少同步代码块,提高性能

2、多线程程序的bug更难发现,要使用更大量的测试数据去监测自己程序的正确性,寻找隐藏的不易被发现的bug,而不是测了一两组数据发现结果正确就认为程序没有问题

3、减少代码中重复的部分,把共用代码抽象对简化代码、提高可读性、debug有很大的帮助,漂亮的代码一定是简洁明了的而不是很深的嵌套,大段的重复

4、类和属性的命名不能偷懒只是自己明白就可以,而是要尽量做到顾名思义,自己写的代码将来很多情况下不是只有自己一个人使用的,好的命名风格会给程序加分

5、完成这三次作业后,发现设计原则中最难实现的还是DIP原则,反观这几次的设计很大一部分实现还是面向Details这也是Metrics度量中圈复杂度和嵌套深度过高的主要原因,在以后的作业中还是要大力改进自己这方面的问题

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325232022&siteId=291194637