在 Python 中,线程调度是指决定在任何给定时间内运行哪个线程的过程。在多线程程序中,多个线程可以独立执行,允许多任务的并行执行。然而,Python 并没有内置的支持来直接控制线程优先级或调度策略。相反,它依赖于操作系统的线程调度器。
Python 线程映射到主机操作系统的本机线程,比如在类 Unix 系统上的 POSIX 线程(pthreads)或 Windows 线程。操作系统调度器管理这些线程的执行,包括上下文切换、线程优先级和调度策略。Python 通过 threading.Timer
类和 sched
模块提供了基本的线程调度能力。
在本教程中,我们将学习 Python 中的基本线程调度知识,包括如何使用 sched
模块来调度任务以及如何使用 threading.Timer
类来进行函数的延迟执行。
使用 Timer 类调度线程
Python 的 threading
模块中的 Timer
类允许你安排一个函数在一段时间后被调用。这个类是 Thread
的子类,是一个创建自定义线程的例子。
你通过调用它的 start()
方法来启动计时器,类似于线程。如果需要,在计时器开始前你可以使用 cancel()
方法来停止它。注意实际的动作执行前的延迟可能与指定的时间间隔不完全匹配。
示例
下面的示例演示了如何使用 threading.Timer()
类来安排和管理 Python 中的任务(自定义线程)的执行。
import threading
import time
def schedule_event(name, start):
now = time.time()
elapsed = int(now - start)
print('Elapsed:', elapsed, 'Name:', name)
start = time.time()
print('START:', time.ctime(start))
t1 = threading.Timer(3, schedule_event, args=('EVENT_1', start))
t2 = threading.Timer(2, schedule_event, args=('EVENT_2', start))
t1.start()
t2.start()
t1.join()
t2.join()
end = time.time()
print('End:', time.ctime(end))
执行上述程序后,它将产生如下输出:
START: Tue Jul 2 14:46:33 2024
Elapsed: 2 Name: EVENT_2
Elapsed: 3 Name: EVENT_1
End: Tue Jul 2 14:46:36 2024
使用 sched 模块调度线程
Python 标准库中的 sched
模块提供了一种调度任务的方法。它实现了一个通用的事件调度器,用于在特定时间运行任务。它提供了类似 Windows 或 Linux 中任务计划者的工具。
sched
模块的关键类和方法
scheduler
类定义在 sched
模块中,用于创建一个调度器对象。以下是该类的语法:
scheduler(timefunc=time.monotonic, delayfunc=time.sleep)
scheduler
类中定义的方法包括:
-
scheduler.enter(delay, priority, action, argument=(), kwargs={})
:事件可以安排在一段时间延迟后运行,或者在特定时间运行。要使用延迟来安排它们,使用 enter()
方法。
-
scheduler.cancel(event)
:从队列中移除事件。如果事件不是当前队列中的事件,此方法将抛出一个 ValueError
。
-
scheduler.run(blocking=True)
:运行所有已安排的事件。
事件可以安排在一段时间延迟后运行,或者在特定时间运行。要使用延迟来安排它们,使用 enter()
方法,它需要四个参数:
示例
下面的示例演示了如何使用 sched
模块来安排事件在延迟后运行。它安排了两个不同的事件。
import sched
import time
scheduler = sched.scheduler(time.time, time.sleep)
def schedule_event(name, start):
now = time.time()
elapsed = int(now - start)
print('elapsed=', elapsed, 'name=', name)
start = time.time()
print('START:', time.ctime(start))
scheduler.enter(2, 1, schedule_event, ('EVENT_1', start))
scheduler.enter(5, 1, schedule_event, ('EVENT_2', start))
scheduler.run()
end = time.time()
print('End:', time.ctime(end))
它将产生如下输出:
START: Tue Jul 2 15:11:48 2024
elapsed= 2 name= EVENT_1
elapsed= 5 name= EVENT_2
End: Tue Jul 2 15:11:53 2024
示例
让我们再看一个例子来更好地理解这个概念。这个例子在 Python 中使用 sched
模块来安排一个函数在四秒钟延迟后执行加法运算。
import sched
from datetime import datetime
import time
def addition(a, b):
print("Performing Addition : ", datetime.now())
print("Time : ", time.monotonic())
print("Result {}+{} =".format(a, b), a + b)
s = sched.scheduler()
print("Start Time : ", datetime.now())
event1 = s.enter(4, 1, addition, argument=(5, 6))
print("Event Created : ", event1)
s.run()
print("End Time : ", datetime.now())
它将产生如下输出:
Start Time : 2024-07-02 15:18:27.862524
Event Created : Event(time=2927111.05638099, priority=1, sequence=0, action=<function addition at 0x7f31f902bd90>, argument=(5, 6), kwargs={})
Performing Addition : 2024-07-02 15:18:31.866381
Time : 2927111.060294749
Result 5+6 = 11
End Time : 2024-07-02 15:18:31.866545