【问题标题】:Python - How to create a new thread that waits for a given time to execute a function [duplicate]Python - 如何创建一个等待给定时间执行函数的新线程[重复]
【发布时间】:2019-04-08 16:46:24
【问题描述】:

我有一个特定类的对象列表,其中每个对象都有一个 unix 时间属性。我想执行一个函数

class Car:

    def __init__(self,  id, time):
       self.id = id
       self.time = time

objct = [Car(i, time_unix[i]) for i in range(10)]

time_unix 是一个 unix 时间列表。我想创建一个新线程,它将与该代码“并行”运行,并在其中检查当前时间。如果当前时间等于对象的unix_time 之一,则会调用一个名为drive 的新函数。

因此,我希望有一个线程在调用drive 函数时持续保持警惕,因为我可能会有其他汽车在各自的驾驶时间到来。

【问题讨论】:

  • @Martijn Pieters 标记为重复的链接是关于以固定的时间间隔(定期)重复安排一个特定事件。这里的这个问题是关于没有固定的一般时间间隔的单个每个对象的调度,并且调度任务的总量是未指定的。
  • @Darkonaut:但解决方案是一样的,使用threading.Timer
  • @Martijn Pieters 如果它是一个重复的问题,难道不是决定这个问题的政策吗?目前尚不清楚您认为哪个答案也是仅通过链接问题即可解决此问题。
  • @Darkonaut:我在那里添加了更多链接。该策略是指向一个可以解决问题的规范。

标签: python multithreading oop real-time unix-timestamp


【解决方案1】:

您可以使用threading.Timer 在指定的时间间隔后在单独的线程中调度目标函数的执行。

定时器对象

这个类代表一个动作,应该在经过一定时间后才运行——一个计时器。 Timer 是 Thread 的子类,因此也可用作创建自定义线程的示例。

与线程一样,定时器通过调用它们的 start() 方法来启动。通过调用 cancel() 方法可以停止计时器(在它的动作开始之前)。计时器在执行其操作之前将等待的时间间隔可能与用户指定的时间间隔不完全相同。 docs

from threading import Timer, current_thread
from datetime import datetime


def drive(car):
    print(f'{datetime.now()} tid:{current_thread()} {car}: brumbrum')


class Car:
    def __init__(self,  id, time):
       self.id = id
       self.time = time


if __name__ == '__main__':

    N_CARS = 5

    time_unix = {k: v for k, v in zip(range(N_CARS), range(N_CARS))}
    cars = [Car(f'car_{i}', time_unix[i]) for i in range(N_CARS)]

    for car in cars:
        interval = car.time  # calculate delay in seconds for execution here
        t = Timer(interval=interval, function=drive, args=(car.id,))
        t.start()

示例输出:

2018-11-05 13:01:50.999886 tid:<Timer(Thread-2, started 139979005781760)> car_0: brumbrum
2018-11-05 13:01:52.000360 tid:<Timer(Thread-3, started 139978997389056)> car_1: brumbrum
2018-11-05 13:01:53.000452 tid:<Timer(Thread-4, started 139979005781760)> car_2: brumbrum
2018-11-05 13:01:54.000533 tid:<Timer(Thread-5, started 139978986825472)> car_3: brumbrum
2018-11-05 13:01:55.000625 tid:<Timer(Thread-6, started 139978978432768)> car_4: brumbrum

Process finished with exit code 0

【讨论】:

  • 这看起来像我需要的。将 t=Timer() t.start() 代码放在 Car 的构造函数中是否是个好主意。所以每次创建汽车时都会调用线程?
  • @user7331538 将是一个选项。你也可以继承Timer 并将这个类命名为Car。我不想将线程埋在普通类中,而是直接将线程子类化以使线程字符更容易被发现。
【解决方案2】:

您不需要时不时地检查当前时间。您可以计算线程需要等待多少秒并调用time.sleep

结合this answer,你得到:

from multiprocessing.dummy import Pool as ThreadPool
from time import sleep

pool = ThreadPool(4) 
cars = [('Car1', 3), ('Car2', 1), ('Car3', 2)]

def start_car(car, time_to_wait):
    sleep(time_to_wait)
    print("Starting %s after %d seconds" % (car, time_to_wait))

pool.starmap(start_car, cars)

它输出:

Starting Car2 after 1 seconds
Starting Car3 after 2 seconds
Starting Car1 after 3 seconds

【讨论】:

  • 但是如果要添加新的 Cars 而我事先不知道我需要 4 个线程怎么办?这就是为什么我要求一个线程不断寻找新来的汽车和他们开始驾驶的时间。换句话说,如果汽车列表随时间变化怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-16
  • 2011-08-13
  • 2018-09-29
  • 2018-03-20
  • 1970-01-01
  • 2015-02-22
  • 1970-01-01
相关资源
最近更新 更多