双触发 2 个线程 运行 并行
Double triggering of 2 threads running parallel
我的代码。它使用内部调度程序启动 2 个线程,每秒打印一次数字
import threading
import time
from datetime import datetime
import schedule
_lock = threading.Lock()
def p(number):
_lock.acquire()
print(number, datetime.now())
_lock.release()
def f(number):
schedule.every(5).seconds.do(p, number)
while True:
schedule.run_pending()
time.sleep(1)
thread = threading.Thread(target=f, args=(1,))
thread2 = threading.Thread(target=f, args=(2,))
thread.start()
thread2.start()
预期输出
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
实际输出(参见 17' 处的 4 个而不是 2 个打印和 27' 处的 3 个而不是 2 个打印)
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
我真的不知道为什么有时线程触发器不止一次起作用。知道我做错了什么吗?
两个线程都向 schedule
添加任务,并且两个线程都执行 run_pending()
。这里可能发生的情况是,一个线程执行 run_pending()
导致两个计划任务都为 运行,但在 run_pending()
完成第一个线程中的执行之前(并将未决任务标记为已完成),第二个线程也介入并执行 run_pending()
,导致所有未决任务被执行两次。
通过将锁从函数 p
移到 run_pending()
周围,我无法复制被触发两次的任务的行为。
def f(number):
schedule.every(5).seconds.do(p, number)
while True:
_lock.acquire()
schedule.run_pending()
_lock.release()
time.sleep(1)
请注意,您也可以重写程序,以便只有一个线程调用 run_pending()
,如下所示:
import threading
import time
from datetime import datetime
import schedule
def p(number):
print(number, datetime.now())
schedule.every(5).seconds.do(p, 1)
schedule.every(5).seconds.do(p, 2)
def task_runner():
while True:
schedule.run_pending()
time.sleep(1)
thread = threading.Thread(target=task_runner)
thread.start()
这是假设您想将主线程用于 运行 计划任务以外的其他事情。或者您可以只在应用程序的事件循环中调用 run_pending()
,而无需将其放在单独的线程中。
我的代码。它使用内部调度程序启动 2 个线程,每秒打印一次数字
import threading
import time
from datetime import datetime
import schedule
_lock = threading.Lock()
def p(number):
_lock.acquire()
print(number, datetime.now())
_lock.release()
def f(number):
schedule.every(5).seconds.do(p, number)
while True:
schedule.run_pending()
time.sleep(1)
thread = threading.Thread(target=f, args=(1,))
thread2 = threading.Thread(target=f, args=(2,))
thread.start()
thread2.start()
预期输出
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
实际输出(参见 17' 处的 4 个而不是 2 个打印和 27' 处的 3 个而不是 2 个打印)
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
我真的不知道为什么有时线程触发器不止一次起作用。知道我做错了什么吗?
两个线程都向 schedule
添加任务,并且两个线程都执行 run_pending()
。这里可能发生的情况是,一个线程执行 run_pending()
导致两个计划任务都为 运行,但在 run_pending()
完成第一个线程中的执行之前(并将未决任务标记为已完成),第二个线程也介入并执行 run_pending()
,导致所有未决任务被执行两次。
通过将锁从函数 p
移到 run_pending()
周围,我无法复制被触发两次的任务的行为。
def f(number):
schedule.every(5).seconds.do(p, number)
while True:
_lock.acquire()
schedule.run_pending()
_lock.release()
time.sleep(1)
请注意,您也可以重写程序,以便只有一个线程调用 run_pending()
,如下所示:
import threading
import time
from datetime import datetime
import schedule
def p(number):
print(number, datetime.now())
schedule.every(5).seconds.do(p, 1)
schedule.every(5).seconds.do(p, 2)
def task_runner():
while True:
schedule.run_pending()
time.sleep(1)
thread = threading.Thread(target=task_runner)
thread.start()
这是假设您想将主线程用于 运行 计划任务以外的其他事情。或者您可以只在应用程序的事件循环中调用 run_pending()
,而无需将其放在单独的线程中。