Beihang OO (2020) Unit 2 Blog Assignment

Unit 2 first operation

Multi-threaded design strategy

The idea of ​​the first job is to design three threads: input thread, scheduler thread and elevator thread. The input thread obtains the request and sends it to the dispatcher thread; the dispatcher thread queries the status of the elevator thread (waiting, docking, and moving) and synthesizes the existing request to allocate the target to the elevator thread; the elevator thread moves according to the allocated target. And carry on the passenger operation.

In order to do this, the input thread and the elevator thread have a shared variable requestQueue to save the request, and the scheduler thread and the elevator thread have a shared variable taskQueue to save the moving target of the elevator. The original intention of this design is to allow different threads to do as much as they can, that is, the input thread is responsible for the requested input, the scheduler thread is responsible for the request scheduling, and the elevator thread is responsible for simulating elevator movement and personnel entry and exit. The advantage of this is that on the one hand, the responsibilities of each thread are very clear, on the other hand, the scheduler facilitates a more flexible scheduling strategy. However, the problem with this is that the elevator thread status obtained by the scheduler is not synchronized with the real-time status of the elevator thread, so more statements need to be added to the scheduler class and elevator class to ensure that the scheduler can update the target for the elevator in time , And the elevator can handle the target correctly. At the same time, another problem is that the scheduler actively allocates targets when there are many situations that need to be considered when multiple elevators are involved, which is more complicated to handle.

Metric analysis

Method complexity (a few of which are more complicated)

Class complexity

Class Diagram

Collaboration diagram

The complexity of this operation is mainly concentrated in the AlsElevator class and the ElevatorController class. The former is mainly related to the collection of elevator movement status and the control of movement. The latter is mainly related to the allocation of targets according to different situations, which is to ensure that different classes have different divisions of labor At the same time, the complexity is dispersed. At the same time, an Elevator interface is reserved. Originally, different types of elevators will be added to the future operations, so the interface is iterated on the side, but because the direction of the expansion of the operation is not considered, the interface is not used in the end.

BUG related

The initial bug encountered during the local testing of this job was mainly the problem of thread exit. The original method was that when the elevator had no target, it would sleep to wait for the controller to allocate the target, but initially due to improper processing, the elevator thread The termination signal response failed, and finally the problem was solved by adding additional judgment.

In terms of mutual testing, automatic testing is still the mainstay. Since there are many thread safety issues in the details of multithreading, the random performance of automatic testing has achieved certain results.

Experience

As the first multi-threaded job, the starting point of this job is relatively high for me. And because of the shortcomings of design flaws, he has spent a lot of energy in ensuring thread synchronization. It is also a warning to him that he must first consider the design and implement the program.

Unit 2 Second homework

Multi-threaded design strategy

Since this operation needs to complete the design of multiple elevators, in order to reduce the coupling between the dispatcher and the elevator, the task allocation scheme is changed to that the elevator actively obtains the target from the dispatcher. Each elevator maintains its own target queue. When the target queue is empty, it sleeps and waits for the scheduler to wake up. The scheduler is responsible for sending a notification to the elevator when a new request comes or the request is not completely processed but the elevator is sleeping. When the dispatcher wakes up multiple elevators, the elevators compete for requests.

Through this process, compared with the first job, the coupling between the scheduler thread and the elevator thread is greatly reduced, and thus the difficulty of ensuring synchronization between threads is greatly reduced.

Metric analysis

Method complexity

Class complexity

Class Diagram

Collaboration diagram

From the complexity point of view, compared with the first job, it is obvious that the complexity is concentrated in the Elevator class. This is because the Elevator class not only needs to complete the simulation of the elevator operation but also needs to handle how to obtain the request and the request The question of how to arrange. From the specific method complexity, it can also be seen that the method in the Elevator class about how to arrange the obtained request to the target queue occupies a large part of the complexity. Although the control strategy was changed, the entire program generally continued the structure of the first job.

BUG related

When doing the second job, the local bug encountered is that the elevator is full to handle the request. The situation is that the elevator is full and cannot continue to accept the request, but the function of scheduling the task does not take this into consideration and continues This was caused by arranging this unhandled request for the elevator.

In the mutual testing phase, for most people, this operation simply added a few elevators compared to the previous operation, and has accumulated some experience in the first operation, so this time although It also adopts the automatic test mode, but hangs for a long time without finding the bug of others.

Experience

Although most people continued the style of the last assignment this time, but because I changed the entire control strategy this time, it caused more changes in the Elevator class and the ElevatorController class. But it is also a timely stop loss. If you follow the idea of ​​the last job, then the job scheduler needs to consider the complexity of the problem for me. It should be very large. Although the complexity of the final program is concentrated in the Elevator class, the overall difficulty of implementation is reduced compared to the previous operation.

Unit 2 third job

Multi-threaded design strategy

This assignment is a continuation of the previous strategy, but it has also made several updates. The first update is support for transfers. I used a more compromised transfer strategy, that is, I implemented a request class and divided all requests into two steps: The first step is which Elevator, the second step is from which elevator can come out, and then according to the situation of entering the elevator, there is this custom request class to generate the elevator floor by itself. In doing so, each requested carriage will be divided into two situations: if the elevator that enters for the first time can be served directly, let this elevator be served directly; if not, the destination floor of the requested class is a certain transit floor so that The second transportation can reach the end. The second update is the elevator's operating mode. Previously, the next target in the target queue was used to move. This update is to sort the target queue in ascending order, and then always move to the end of the queue closer to the current floor. This method can be implemented in much less detail than the previous method, so performance may be lost, but it is much simpler. The last update is that the dispatcher will add an optional destination layer while notifying the elevator to help the elevator reduce the complexity of decision-making.

Metric analysis

Method complexity

Class complexity

Class Diagram

Collaboration diagram

For the newly added transfer request for this job, my idea is to imitate people to handle the transfer operation themselves, so a new MyRequest class was created to handle the transfer-related operations. Because this new class shares many and many operations related to target processing, and also simplifies the strategy of elevator operation, several classes in this operation have a certain degree of reduction compared to the previous operation. , Especially the Elevator class, which basically returns to the role of the first job, mainly dealing with the simulation of elevator movement. In addition to the newly added MyRequest class, the relationship between several other classes is similar to the second operation.

BUG related

At the beginning of this job, I found a bug in the local test: Because my elevator is designed to stop sending requests when there are no more requests, and the request queue is empty, it will start to send a termination signal downwards, and the task will end when the elevator is transported. Procedures, but sometimes there may be people in the elevator who need to transfer, which will result in the end of the procedure before the personnel are sent.

Another bug was generated during the mutual testing phase, and was finally found to be a deadlock bug: there is a relationship between the elevator and the dispatcher that wakes up each other. When the elevator status is updated, or a new request comes, the dispatcher will Was awakened; when the scheduler finds that there are unprocessed requests and an elevator is sleeping, the scheduler will wake up the elevator. However, there is a problem with this relationship. When the elevator is about to go to sleep, the dispatcher checks that there is no dispatchable elevator and then goes to sleep, but the elevator will go to sleep at the next moment, so there will be a deadlock situation waiting for each other. , And finally compromise this bug by setting the upper limit of wait time.

Experience and summary

With the addition of the MyRequest class this time, I think it balances the complexity of the different classes to a certain extent, and at the same time has a clearer division of responsibilities between classes than the previous job. But an issue that I have n’t considered in these three jobs is whether the scheduler needs to be set as a process separately. Now let ’s consider that the scheduler ’s operation scenario is completely updated when the external state (including new requests) , Elevator status update, etc.) only need to be operated, so there is no need to set up as a process, let the input process and the Elevator process directly operate the scheduler as a shared resource, and at the same time, there is an advantage that it can be Not considering the synchronization between the elevator thread and the scheduler thread, it can also make the implementation more concise and safe to a certain extent.

For the extensibility of the program, the case where the elevator is temporarily deleted and the purpose of passengers to change halfway is considered. Temporary deletion of the elevator can be achieved by deleting the elevator from the elevator set, and using the endSignal signal to let the elevator end after transporting and playing this task. For passengers to change destinations temporarily, because the MyRequest class is a class that mimics the behavior of passengers, so by changing some properties of the MyRequest object, you can simply achieve temporary passenger transfers.

 

Guess you like

Origin www.cnblogs.com/8igfive/p/12709223.html