Mô phỏng hệ thống quản lý nhiệm vụ¶
Tóm lược nội dung
Bài này trình bày cách giải bài toán quản lý các nhiệm vụ của hệ thống bằng cấu trúc hàng đợi.
Bài toán¶
Yêu cầu:
Viết chương trình mô phỏng một hệ thống điều khiển thiết bị IoT thực thi các nhiệm vụ. Trong đó, hệ thống dùng cấu trúc hàng đợi để quản lý nhiệm vụ với các lệnh sau:
ADD task: thêm nhiệm vụtaskvào hàng đợi.RUN: thực hiện nhiệm vụ ở đầu hàng đợi.-
CANCEL task: huỷ nhiệm vụtask.Khi huỷ một nhiệm vụ
tasknào đó ở giữa hàng đợi, những nhiệm vụ đứng trướctasksẽ lần lượt được lấy ra và đưa lại vào cuối hàng đợi nhằm bảo đảm nguyên tắc FIFO, cho đến khi tìm thấy nhiệm vụtaskcần huỷ nằm ở đầu hàng đợi.
Với mỗi lệnh và nhiệm vụ, ta chỉ cần in ra thông báo về lệnh và nhiệm vụ đó.
Đầu vào:
Gồm nhiều dòng, mỗi dòng biểu thị một lệnh.
ADD taskRUNCANCEL task
Đầu ra:
Các thông báo và tình trạng của hàng đợi tương ứng với mỗi dòng lệnh trong dữ liệu đầu vào.
Bộ kiểm thử:
Đầu vào:
ADD READ_SENSOR
ADD WRITE_LOG
RUN
ADD READ_SENSOR
ADD WRITE_LOG
CANCEL WRITE_LOG
ADD CLEAN_MEMORY
CANCEL CLEAN_MEMORY
ADD SYNC_SERVER
RUN
RUN
RUN
Đầu ra:
Thêm nhiệm vụ READ_SENSOR
Hàng đợi: ['READ_SENSOR']
Thêm nhiệm vụ WRITE_LOG
Hàng đợi: ['READ_SENSOR', 'WRITE_LOG']
Đang thực thi nhiệm vụ READ_SENSOR
Hàng đợi: ['WRITE_LOG']
Thêm nhiệm vụ READ_SENSOR
Hàng đợi: ['WRITE_LOG', 'READ_SENSOR']
Thêm nhiệm vụ WRITE_LOG
Hàng đợi: ['WRITE_LOG', 'READ_SENSOR', 'WRITE_LOG']
Huỷ nhiệm vụ WRITE_LOG
Hàng đợi: ['READ_SENSOR', 'WRITE_LOG']
Thêm nhiệm vụ CLEAN_MEMORY
Hàng đợi: ['READ_SENSOR', 'WRITE_LOG', 'CLEAN_MEMORY']
Huỷ nhiệm vụ CLEAN_MEMORY
Hàng đợi: ['READ_SENSOR', 'WRITE_LOG']
Thêm nhiệm vụ SYNC_SERVER
Hàng đợi: ['READ_SENSOR', 'WRITE_LOG', 'SYNC_SERVER']
Đang thực thi nhiệm vụ READ_SENSOR
Hàng đợi: ['WRITE_LOG', 'SYNC_SERVER']
Đang thực thi nhiệm vụ WRITE_LOG
Hàng đợi: ['SYNC_SERVER']
Đang thực thi nhiệm vụ SYNC_SERVER
Hàng đợi: []
Cách giải đề xuất¶
Ý tưởng chính¶
Ta viết các hàm add(), run() và cancel() để xử lý các lệnh tương ứng.
-
Trong mỗi hàm, việc xử lý lệnh và nhiệm vụ không có gì phức tạp, chỉ đơn giản là gọi hàm
print()để in ra thông báo liên quan. -
Đối với hàm huỷ
cancel(), ta dùng vòng lặp để lấy ra từng nhiệm vụ trong hàng đợi cho đến khi tìm thấy nhiệm vụ cần huỷ.
Viết thêm hàm process() để xử lý từng dòng trong dữ liệu đầu vào. Với mỗi dòng, ta gọi hàm tương ứng một trong ba hàm đã viết trên ra xử lý.
Viết chương trình¶
1. Nạp module và khai báo biến¶
Nạp lớp Queue của module queue.
Khai báo biến data chứa dữ liệu đầu vào.
Khởi tạo hàng đợi task_queue dùng để chứa các phần tử là nhiệm vụ.
2. Đọc dữ liệu đầu vào¶
Viết hàm parse_data() để đọc dữ liệu đầu vào trong biến data.
Hàm này trả về danh sách các dòng lệnh.
-
Tham số
ddùng để nhận dữ liệu đầu vào. -
strip()được thực hiện trước, dùng để cắt bỏ các khoảng trắng ở hai đầu củad.splitlines()được thực hiện sau, dùng để phân tách thành các dòng lệnh riêng lẻ.
3. Xử lý¶
Viết hàm add() để xử lý lệnh ADD. Việc xử lý bao gồm:
- Đưa nhiệm vụ vào hàng đợi
task_queue. - In ra thông báo liên quan.
Hàm này gồm một tham số là nhiệm vụ cần đưa vào hàng đợi, đặt là task.
Viết hàm run() để xử lý lệnh RUN. Việc xử lý bao gồm:
- Lấy ra nhiệm vụ nằm ở đầu hàng đợi.
- In ra thông báo liên quan.
Hàm này không có tham số vì nhiệm vụ là giá trị của phần tử nằm ở đầu hàng đợi.
get()vừa lấy giá trị của phần tử ở đầu hàng đợi, vừa xoá nó khỏi hàng đợi.
Viết hàm cancel() để xử lý lệnh CANCEL.
Hàm này gồm một tham số là nhiệm vụ cần huỷ, đặt là task.
Ta dùng vòng lặp while để xác định xem phần tử nằm ở đầu hàng đợi có phải là nhiệm vụ cần huỷ task hay không:
- Nếu phần tử đầu hàng đợi là nhiệm vụ cần huỷ thì in ra thông báo liên quan.
- Ngược lại, nếu phần tử đầu hàng đợi không phải là nhiệm vụ cần huỷ thì đưa nhiệm vụ này ra sau cùng, tức đưa lại vào cuối hàng đợi
task_queue.
Viết hàm process() để gọi các hàm trên.
Hàm này gồm một tham số là danh sách các dòng lệnh có được từ hàm parse_data(), đặt là lines.
Ta dùng vòng lặp for để duyệt từng dòng lệnh, lặp thao tác:
- Phân tách hai thành phần trong mỗi dòng vào một danh sách
C. - Xét thành phần đầu tiên, là
C[0], đang chứa lệnh gì. - Ứng với mỗi lệnh
C[0], ta gọi hàm tương ứng đã viết ở trên.
4. Chương trình chính¶
Trong chương trình chính, ta gọi các hàm đã viết ra thực hiện:
- Hàm
parse_data()để đọc dữ liệu đầu vào. - Hàm
process()để xử lý dữ liệu.
Chạy chương trình trên và đối chiếu kết quả với đầu ra trong bộ kiểm thử.
Mã nguồn¶
Code đầy đủ được đặt tại: