Search code examples
pythonmultithreadingoopreal-timeunix-timestamp

Python - How to create a new thread that waits for a given time to execute a function


I have a list of objects of a particular class where each object has a unix time attribute. I would like to execute a function

class Car:

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

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

where time_unix is a list of unix times. I would like to create a new thread that will run 'in parallel' to this code where it checks the current time. If the current time is equal to one of the object's unix_time, a new function called drive will be invoked.

So I would like to have a thread that is on constant alert for invoking a drive function since I might have other cars coming in with their respective time to drive.


Solution

  • You can use threading.Timer for scheduling execution of a target function in a separate thread after a specified time interval.

    Timer Objects

    This class represents an action that should be run only after a certain amount of time has passed — a timer. Timer is a subclass of Thread and as such also functions as an example of creating custom threads.

    Timers are started, as with threads, by calling their start() method. The timer can be stopped (before its action has begun) by calling the cancel() method. The interval the timer will wait before executing its action may not be exactly the same as the interval specified by the user. 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()
    

    Example Output:

    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