Python 多线程如何按照任务优先级顺序执行,并根据任务分配来申请线程锁

文章目录


项目介绍

模拟一个场景,有一个工作站,工作站内有一台机器人负责抓取站内四个瓶子进行一系列工作流程,如扫描、称重、加热等动作,但瓶子加热需要较长的时间,机器人在将瓶子放到加热台后可以先执行其他任务,这样可以在将四个瓶子放到加热台后再集中处理之后的流程,在其他情况下为了连贯可以同一个瓶子处理完再按顺序执行其他瓶子的流程

此场景需要用到知识点:
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):
        self.name = _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(self.name, 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):
        self.name = "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、如有好的方式欢迎赐教,谢谢

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值