python - 2个并行线程的双重触发
问题描述
我的代码。它使用内部调度程序启动 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
实际输出(见 4 而不是 2 打印在 17' 和 3 而不是 2 在 27' 打印)
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()
这是假设您想将主线程用于运行计划任务以外的其他事情。或者您可以只在应用程序的事件循环中调用 torun_pending()
而无需将其放在单独的线程中。
推荐阅读
- build - 尝试构建 next.js 示例应用程序时从 Terser 获取 TypeError
- android - 如何在 Android 应用程序中结合 RxJava 中的网络和数据库更新
- reactjs - 路由参数更改时组件不会重新加载新数据
- php - $_POST 在 ajax 向 php 页面发送请求后返回空数组
- c - 逐行读取文件并捕获该行单词
- android-fragments - 新片段打开后 Kotlin FAB 仍可点击
- java - 使用 java.time 解析具有多种不同格式的日期的 Java 或 Scala 快速方法
- angular-cli - 角度 5 到 7 更新后无法构建产品,更简洁的错误
- java - Spring Boot 2.0 中的 RedisCacheManager.setCacheNames
- android - 我在 bintray 上将库添加到 maven 但无法从 gradle 下载?(安卓)