文章目录
- 项目介绍
- 总结
项目介绍
模拟一个场景,有一个工作站,工作站内有一台机器人负责抓取站内四个瓶子进行一系列工作流程,如扫描、称重、加热等动作,但瓶子加热需要较长的时间,机器人在将瓶子放到加热台后可以先执行其他任务,这样可以在将四个瓶子放到加热台后再集中处理之后的流程,在其他情况下为了连贯可以同一个瓶子处理完再按顺序执行其他瓶子的流程
此场景需要用到知识点:
1、多线程处理每个瓶子的任务
2、在处理加热流程后,如果需要执行其他任务需要分配每个瓶子任务的优先级,然后通过流程的优先级来决定哪个线程需要执行
3、多线程运行时需要申请线程锁,在此之前需要通过流程的优先级来决定是否需要申请线程锁
4、此场景至少需要流程的类及机器人的类声明来处理相关逻辑
5、类之间通过间接调用来引用其他类的方法
代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Version : PyCharm
# @Time : 2023/4/1 6:58
# @Author : Pitt.Ding
# @File : Robot_Pour_MultiTask.py
# @Description : 模拟机器人倒水及加热、测温的多任务流程
import random
import time
import threading
# 声明一个工作流程类,建立流程运行的一般格式
class WorkProcess:
def __init__(self, _name, _priority):
= _name
self.process_finished = False
self.process_priority = _priority
# 模拟定义了每个流程的工作时间及进度
def start(self):
self.process_finished = False
_worktime = random.randrange(3, 5)
for i in range(_worktime):
# print("Process {0} has working {1} seconds".format(, i))
time.sleep(1)
self.process_finished = True
# 通过间接调用来调用目标的方法
def request_robot(self, _robot):
try:
if type(_robot) == Robot:
if not _robot.process_busy:
_robot.receive_work(self.start)
else:
print("Robot is busying in process!")
else:
print("Request object is not Robot Class!")
except ValueError:
print("Request failed")
# 声明一个物品的流程类,其中可能会包含多个流程,并且每个流程按照步骤来执行,通过itemProcess来处理多线程运行的优先级
class ItemProcess:
def __init__(self, item_process_name, _item_index, _thread_priority_list, process_name_list):
# 通过用户设置的工艺名称列表来生成每个物料的工作流程
self.process = [WorkProcess(i[0], i[1]) for i in process_name_list]
self.item_process_name = item_process_name
self.item_index = _item_index
self.tread_priority_list = _thread_priority_list
# 用标志位来判断当前线程是否已经申请线程锁
self.lock_thread = False
def run(self, _robot, _thread_lock, _thread_priority_list):
for _index in range(len(self.process)):
_process = self.process[_index]
while not _process.process_finished:
self.tread_priority_list[self.item_index] = _process.process_priority
# print(self.tread_priority_list)
time.sleep(0.1)
if _process.process_priority >= max(self.tread_priority_list) and max(self.tread_priority_list) > 0:
# print("Find max priority {0}".format(_process.process_priority))
if self.item_index > 0:
for i in range(self.item_index):
# print("Max priority {0}, i: {1}, list_priority_i:{2}".format(_process.process_priority, i, self.tread_priority_list[i]))
if _process.process_priority == self.tread_priority_list[i]:
break
# 检查前面没有同优先级的线程
if i == self.item_index-1:
if not self.lock_thread:
_thread_lock.acquire()
self.lock_thread = True
print(">>>>>>>>Item {0}: process {1} is working".format(self.item_process_name, _process.name))
_process.request_robot(_robot)
# 判断下一个process的优先权是否依然是最大的,如果是则不释放线程锁
if _index+1 <=len(self.process)-1:
if self.process[_index+1].process_priority < max(self.tread_priority_list):
_thread_lock.release()
self.lock_thread = False
else:
if not self.lock_thread:
# 通过标志位来检查当前线程是否已经申请线程锁,如果多次申请线程锁则程序会全部停止
_thread_lock.acquire()
self.lock_thread = True
print(">>>>>>>>Item {0}: process {1} is working".format(self.item_process_name, _process.name))
_process.request_robot(_robot)
# 判断下一个process的优先权是否依然是最大的,如果是则不释放线程锁
if _index + 1 <= len(self.process)-1:
if self.process[_index + 1].process_priority < max(self.tread_priority_list):
_thread_lock.release()
self.lock_thread = False
# 张程流程全部执行完毕,将优先权设置复位为0
self.tread_priority_list[self.item_index] = 0
print(self.tread_priority_list)
print(">>>>>>>>Item {0}: process Finished".format(self.item_process_name))
# 线程的流程全部执行完毕,释放线程锁
_thread_lock.release()
self.lock_thread = False
# 声明一个机器人类,用于声明机器人工作的流程
class Robot:
def __init__(self):
= "Robot"
self.process_busy = False
# 通过receive_work方法来调用目标的方法
def receive_work(self, fun):
if not self.process_busy:
self.run_process(fun)
return True
else:
return False
def run_process(self, fun):
self.process_busy = True
fun()
self.process_busy = False
if __name__ == "__main__":
# 工艺名称及优先权列表
process_name = [["scan", 2], ["weight", 3], ["heat", 1], ["taste1", 2], ["cool", 2], ["taste2", 2]]
list_thread_priority = [0 for i in range(len(process_name))]
robot = Robot()
# 为每个物料声明了一套工艺流程
item_process1 = ItemProcess("Item1", 0, list_thread_priority, process_name)
item_process2 = ItemProcess("Item2", 1, list_thread_priority, process_name)
item_process3 = ItemProcess("Item3", 2, list_thread_priority, process_name)
item_process4 = ItemProcess("Item4", 3, list_thread_priority, process_name)
# 声明线程锁
thread_lock = threading.Lock()
# 分别为每个物料工艺流程分配了一个线程
thread1 = threading.Thread(target=item_process1.run, args=(robot, thread_lock, list_thread_priority))
thread2 = threading.Thread(target=item_process2.run, args=(robot, thread_lock, list_thread_priority))
thread3 = threading.Thread(target=item_process3.run, args=(robot, thread_lock, list_thread_priority))
thread4 = threading.Thread(target=item_process4.run, args=(robot, thread_lock, list_thread_priority))
# 启动四个线程
thread1.start()
thread2.start()
thread3.start()
thread4.start()
输出结果:
Item Item1: process scan is working
Item Item1: process weight is working
Item Item2: process scan is working
Item Item2: process weight is working
Item Item3: process scan is working
Item Item3: process weight is working
Item Item4: process scan is working
Item Item4: process weight is working
Item Item1: process heat is working
Item Item1: process taste1 is working
Item Item1: process cool is working
Item Item1: process taste2 is working
[0, 1, 1, 1, 0, 0]
Item Item1: process Finished
Item Item2: process heat is working
Item Item2: process taste1 is working
Item Item2: process cool is working
Item Item2: process taste2 is working
[0, 0, 1, 1, 0, 0]
Item Item2: process Finished
Item Item3: process heat is working
Item Item3: process taste1 is working
Item Item3: process cool is working
Item Item3: process taste2 is working
[0, 0, 0, 1, 0, 0]
Item Item3: process Finished
Item Item4: process heat is working
Item Item4: process taste1 is working
Item Item4: process cool is working
Item Item4: process taste2 is working
[0, 0, 0, 0, 0, 0]
Item Item4: process Finished
总结
1、线程锁的申请即不能重复申请也不能在当前线程没有获得线程锁的情况下直接释放线程锁;如果重复申请线程锁则程序会直接停止运行,如果在其他线程没有释放线程锁的情况下直接释放线程锁则也可以将锁释放掉,此时会导致线程数据错乱
2、在类的声明及方法调用的过程中尽量遵守高内聚、低耦合的原则,将需要调用的外部数据通过输入输出参数来转接
3、如有好的方式欢迎赐教,谢谢