需求:
一共有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