python - 以周期性间隔记录无限数据

标签 python multithreading

我有无限数量的条目正在通过网络界面输入。在每分钟的基础上,我想将最后一小时收到的元素转储到一个适当命名的文件中 (datetime.now().strftime('%Y_%m_%d_%H_%M' )).
到目前为止,这是我的设计:

线程 1

不断接收输入并添加到 data_dict 结构:
{datetime.now().strftime('%Y_%m_%d_%H_%M') : []}

线程 2

休眠一分钟并写入 data_dict[(datetime.now() - timedelta(minutes=1)).strftime('%Y_%m_%d_%H_%M')]

问题

  1. 以这种方式使用 dict 是线程安全的吗?
  2. 这是一个好的设计吗? :)

最佳答案

1) 这是(几乎)线程安全的。 dict 上的各个操作是线程安全的,您的读取线程永远不应该从仍在写入的键中读取。异常(exception)情况是以下竞争条件,它依赖于接近分钟边界发生的上下文切换。

线程 1:在 2014-05-20 13:37:59.999 收到一条消息,然后被抢占

线程 2:检查时间(现在是 2014-05-20 13:38:00.000)所以它从 2014_05_20_13_37 开始读取

线程 1:将其消息附加到 2014_05_20_13_37 队列的末尾

2) 不,这不是好的设计,不仅仅是因为线程安全条件中存在边缘情况。如果你需要保证每一分钟都做某事, sleep 是一种非常容易出错的方法。首先, sleep 操作不会在给定的时间内完全 sleep 。它至少睡了那么长的时间。其次,即使它是准确的,您的其余操作仍然需要一些时间,这意味着您的 sleep 调用之间会有毫秒数的漂移。这两个因素可能会导致您每 6000-60000 分钟就错过一分钟。

忽略第 1 部分中的竞争条件,我将执行以下操作:

def generate_times():
    now = datetime.datetime.now()
    next_time = datetime.datetime(now.year, now.month, now.day, now.hour, now.minute)
    while True:
        yield next_time
        next_time += datetime.timedelta(minute=1)

def past_times():
    for time in generate_times():
        while time > datetime.datetime.now() - datetime.timedelta(minute=1):
            time.sleep(1.0)
        yield time

第一个函数创建一个生成器,生成所有的分钟时间,第二个函数确保时间已经过去。

处理第一部分中的竞争条件的最简单方法可能是让线程 2 滞后 2 分钟,而不是仅滞后 1 分钟(或者 1 分 7 秒或 16 分钟,无论您想要什么)。这仍然不是万无一失的:如果你有一些东西让你的内核停滞很长时间,那么这些竞争条件仍然可能发生,但这是一个完美的 Storm 场景。

如果你想 100% 正确,那么线程 1 需要保持一个时间戳来跟踪它写出日志的最新时间,但是你将要研究非阻塞 IO 以确保你的最后一次如果没有线程第一个被卡住等待记录,日志不会停止。我,我自己,只会在 past_times 函数中使用 2 分钟而不是 1 分钟,除非这是生命所依赖的东西的关键任务日志记录。

关于python - 以周期性间隔记录无限数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23797195/

相关文章:

java - Java Thread.sleep() 是否释放处理器?

python - 如何使用 GET 请求将参数传递给 AWS Lambda 函数?

python - 为具有多个输入和输出的函数并行化 for 循环

python - 根据 Pandas 数据框中的另一列获取两列的频率计数

Python strftime %A 定长

Java nio服务端客户端异步

c# - BackgroundWorker.RunWorkerCompleted 和线程

multithreading - D编程语言中控制并行线程的数量

java - 多线程中的ExecuteQuery关闭hsqldb数据库连接

解析格式化字符串并从中获取字典的 Pythonic 方法