【Python】多任务执行与停止控制实现

需求:
一共有5个任务等待执行,触发执行后,某一时间按停止,已经运行的任务返回实际状态,没有运行的状态就改为abort;

code

import threading
import time
import random
from enum import Enum, auto


class TaskStatus(Enum):
    PENDING = auto()
    RUNNING = auto()
    COMPLETED = auto()
    FAILED = auto()
    ABORTED = auto()


class TaskController:
    def __init__(self, num_tasks=5):
        self.tasks = [{"id": i, "status": TaskStatus.PENDING} for i in range(num_tasks)]
        self.lock = threading.Lock()
        self.stop_event = threading.Event()
        self.completed_tasks = 0
        self.total_tasks = num_tasks

    def execute_task(self, task_id):
        # 模拟任务执行
        duration = random.uniform(0.5, 2.0)
        time.sleep(duration)

        # 随机决定任务成功还是失败
        success = random.choice([True, False, True])  # 2/3概率成功

        with self.lock:
            if self.stop_event.is_set():
                self.tasks[task_id]["status"] = TaskStatus.ABORTED
                return

            if success:
                self.tasks[task_id]["status"] = TaskStatus.COMPLETED
            else:
                self.tasks[task_id]["status"] = TaskStatus.FAILED

            self.completed_tasks += 1

    def start_execution(self):
        print("Starting task execution...")
        self.stop_event.clear()
        threads = []

        for task in self.tasks:
            print(f"Starting task {task['id']}...")
            with self.lock:
                if self.stop_event.is_set():
                    task["status"] = TaskStatus.ABORTED
                    continue

                task["status"] = TaskStatus.RUNNING
                t = threading.Thread(target=self.execute_task, args=(task["id"],))
                threads.append(t)
                t.start()

        return threads

    def stop_execution(self):
        print("\nStopping execution...")
        self.stop_event.set()

        # 等待所有线程完成(实际应用中可能需要超时)
        for t in threading.enumerate():
            if t != threading.current_thread():
                t.join()

        # 确保所有未启动的任务标记为ABORTED
        with self.lock:
            for task in self.tasks:
                if task["status"] == TaskStatus.PENDING:
                    task["status"] = TaskStatus.ABORTED

        print("Execution stopped.")

    def get_task_statuses(self):
        with self.lock:
            return [task["status"] for task in self.tasks]

    def print_statuses(self):
        statuses = self.get_task_statuses()
        for i, status in enumerate(statuses):
            print(f"Task {i}: {status.name}")
        print()


# 使用示例
if __name__ == "__main__":
    controller = TaskController(5)

    # 启动任务执行
    threads = controller.start_execution()

    # 模拟用户在一段时间后停止
    time.sleep(1)  # 等待1秒后停止

    # 停止执行
    controller.stop_execution()

    # 打印最终状态
    print("\nFinal task statuses:")
    controller.print_statuses()

代码说明
任务状态枚举:定义了5种任务状态:

PENDING: 等待执行

RUNNING: 正在执行

COMPLETED: 完成

FAILED: 失败

ABORTED: 已中止

TaskController类:

execute_task(): 模拟任务执行,随机耗时和随机成功/失败

start_execution(): 启动所有任务,每个任务在单独线程中运行

stop_execution(): 设置停止事件,并标记所有未运行任务为ABORTED

get_task_statuses(): 获取所有任务状态

print_statuses(): 打印任务状态

线程安全:

使用threading.Lock确保对共享数据的安全访问

使用threading.Event作为停止信号

使用示例:

创建控制器并启动5个任务

1秒后停止执行

打印最终状态

log

Starting task execution...
Starting task 0...
Starting task 1...
Starting task 2...
Starting task 3...
Starting task 4...

Stopping execution...
Execution stopped.

Final task statuses:
Task 0: ABORTED
Task 1: COMPLETED
Task 2: ABORTED
Task 3: ABORTED
Task 4: ABORTED

添加任务优先级 & 任务结果收集功能

import threading
import time
import random
from enum import Enum, auto
from queue import PriorityQueue
from dataclasses import dataclass, field
from typing import Any

class TaskStatus(Enum):
    PENDING = auto()
    RUNNING = auto()
    COMPLETED = auto()
    FAILED = auto()
    ABORTED = auto()

@dataclass(order=True)
class PrioritizedTask:
    priority: int
    task: Any=field(compare=False)

class TaskController:
    def __init__(self, num_tasks=5):
        self.tasks = []
        self.results = {}
        self.lock = threading.Lock()
        self.stop_event = threading.Event()
        self.completed_tasks = 0
        self.total_tasks = num_tasks
        self.task_queue = PriorityQueue()
        
        # 初始化任务,随机分配优先级(1-5,1为最高优先级)
        for i in range(num_tasks):
            priority = random.randint(1, 5)
            task = {
                "id": i,
                "status": TaskStatus.PENDING,
                "priority": priority,
                "result": None
            }
            self.tasks.append(task)
            self.task_queue.put(PrioritizedTask(priority, task))
    
    def execute_task(self, task):
        # 模拟任务执行
        duration = random.uniform(0.5, 2.0)
        time.sleep(duration)
        
        # 随机决定任务成功还是失败
        success = random.choice([True, False, True])  # 2/3概率成功
        result = f"Result of task {task['id']}" if success else None
        
        with self.lock:
            if self.stop_event.is_set():
                task["status"] = TaskStatus.ABORTED
                task["result"] = "Aborted due to stop signal"
                self.results[task["id"]] = task["result"]
                return
            
            if success:
                task["status"] = TaskStatus.COMPLETED
                task["result"] = result
            else:
                task["status"] = TaskStatus.FAILED
                task["result"] = "Task failed"
            
            self.results[task["id"]] = task["result"]
            self.completed_tasks += 1
    
    def start_execution(self):
        print("Starting task execution...")
        print("Initial task priorities:")
        self.print_task_priorities()
        
        self.stop_event.clear()
        threads = []
        
        while not self.task_queue.empty():
            with self.lock:
                if self.stop_event.is_set():
                    # 清空队列并标记剩余任务为ABORTED
                    while not self.task_queue.empty():
                        ptask = self.task_queue.get()
                        ptask.task["status"] = TaskStatus.ABORTED
                        ptask.task["result"] = "Aborted before execution"
                        self.results[ptask.task["id"]] = ptask.task["result"]
                    break
                
                ptask = self.task_queue.get()
                task = ptask.task
                task["status"] = TaskStatus.RUNNING
                print(f"Starting task {task['id']} with priority {task['priority']}")
                
                t = threading.Thread(target=self.execute_task, args=(task,))
                threads.append(t)
                t.start()
        
        return threads
    
    def stop_execution(self):
        print("\nStopping execution...")
        self.stop_event.set()
        
        # 等待所有线程完成(实际应用中可能需要超时)
        for t in threading.enumerate():
            if t != threading.current_thread():
                t.join()
        
        # 确保所有未启动的任务标记为ABORTED
        with self.lock:
            while not self.task_queue.empty():
                ptask = self.task_queue.get()
                ptask.task["status"] = TaskStatus.ABORTED
                ptask.task["result"] = "Aborted after stop signal"
                self.results[ptask.task["id"]] = ptask.task["result"]
        
        print("Execution stopped.")
    
    def get_task_statuses(self):
        with self.lock:
            return [(task["id"], task["status"], task["priority"], task["result"]) for task in self.tasks]
    
    def get_task_results(self):
        with self.lock:
            return self.results
    
    def print_statuses(self):
        statuses = self.get_task_statuses()
        print("\nTask ID | Status     | Priority | Result")
        print("----------------------------------------")
        for task_id, status, priority, result in statuses:
            print(f"{task_id:6}  | {status.name:9}  | {priority:8} | {result}")
    
    def print_task_priorities(self):
        priorities = [(task["id"], task["priority"]) for task in self.tasks]
        print("Task ID | Priority")
        print("------------------")
        for task_id, priority in priorities:
            print(f"{task_id:6}  | {priority:8}")

# 使用示例
if __name__ == "__main__":
    controller = TaskController(5)
    
    # 启动任务执行
    threads = controller.start_execution()
    
    # 模拟用户在一段时间后停止
    time.sleep(1)  # 等待1秒后停止
    
    # 停止执行
    controller.stop_execution()
    
    # 打印最终状态和结果
    print("\nFinal task statuses and results:")
    controller.print_statuses()
    
    print("\nAll results:")
    results = controller.get_task_results()
    for task_id, result in results.items():
        print(f"Task {task_id}: {result}")

log

Starting task execution...
Initial task priorities:
Task ID | Priority
------------------
     0  |        2
     1  |        5
     2  |        2
     3  |        5
     4  |        5
Starting task 0 with priority 2
Starting task 2 with priority 2
Starting task 4 with priority 5
Starting task 1 with priority 5
Starting task 3 with priority 5

Stopping execution...
Execution stopped.

Final task statuses and results:

Task ID | Status     | Priority | Result
----------------------------------------
     0  | ABORTED    |        2 | Aborted due to stop signal
     1  | FAILED     |        5 | Task failed
     2  | COMPLETED  |        2 | Result of task 2
     3  | ABORTED    |        5 | Aborted due to stop signal
     4  | ABORTED    |        5 | Aborted due to stop signal

All results:
Task 1: Task failed
Task 2: Result of task 2
Task 4: Aborted due to stop signal
Task 3: Aborted due to stop signal
Task 0: Aborted due to stop signal

你可能感兴趣的:(Python,实用工具,python,开发语言,数据库)