Threading¶
The Scheduler is thread safe and supports parallel execution
of pending Jobs.
Jobs with a relevant execution time or blocking IO operations
can delay each other.
Warning
When running Jobs in parallel, be sure that possible side effects
of the scheduled functions are implemented in a thread safe manner.
The following examples show the difference between concurrent and parallel
Schedulers:
Concurrent execution¶
By default the Scheduler will execute its
Jobs sequentially. The total duration when executing multiple
Jobs will therefore be greater than the sum of the individual
run times.
>>> import datetime as dt
>>> import time
>>> from scheduler import Scheduler
>>> def sleep(secs: float):
... time.sleep(secs)
...
>>> schedule = Scheduler()
>>> job_1 = schedule.once(dt.timedelta(), sleep, kwargs={"secs": 0.1})
>>> job_2 = schedule.once(dt.timedelta(), sleep, kwargs={"secs": 0.1})
>>> start_time = time.perf_counter()
>>> n_exec = schedule.exec_jobs()
>>> total_seconds = time.perf_counter() - start_time
>>> n_exec
2
>>> 0.2 < total_seconds and total_seconds < 0.21
True
Parallel execution¶
The number of worker threads for the Scheduler can be defined
with the n_threads argument. For n_threads = 0 the Scheduler
will spawn a seperate worker thread for every pending Job.
>>> import datetime as dt
>>> import time
>>> from scheduler import Scheduler
>>> def sleep(secs: float):
... time.sleep(secs)
...
>>> schedule = Scheduler(n_threads=0)
>>> job_1 = schedule.once(dt.timedelta(), sleep, kwargs={"secs": 0.1})
>>> job_2 = schedule.once(dt.timedelta(), sleep, kwargs={"secs": 0.1})
>>> start_time = time.perf_counter()
>>> n_exec = schedule.exec_jobs()
>>> total_seconds = time.perf_counter() - start_time
>>> n_exec
2
>>> 0.1 < total_seconds and total_seconds < 0.11
True