【问题标题】:Signaling between threads in PythonPython中线程之间的信号传递
【发布时间】:2012-05-15 15:05:41
【问题描述】:

我正在开发一个实时数据采集器。我有一个 while True 循环,在其中,我生成了执行相对较小任务的线程(我正在通过 HTTP 查询第 3 方 API,为了实现快速并行查询)。

每个线程都负责更新特定的数据系列。这可能需要 2、3 甚至 5 秒。但是,我的 while True 循环产生线程的速度可能比线程完成所需的时间要快。因此,我需要生成的线程等待它们之前的线程完成。

一般来说,线程需要多长时间才能完成是无法预测的,因为线程会查询 HTTP 服务器...

我正在考虑为每个线程创建一个命名信号量,然后如果为特定系列生成的线程发现以前的线程在同一系列上工作,它将等待。

我能看到的唯一问题是线程可能积压..

这里最好的解决方案是什么?我应该研究像芹菜这样的东西吗?我目前正在使用线程模块。

谢谢!

【问题讨论】:

  • 如果任务受 CPU 限制,那么由于 GIL,使用线程不会给您带来性能优势。
  • 如果你有并行数据但没有队列,那么你做错了。您应该有一些工作人员从一个队列中获取他们的输入(即要下载的一个 url)并将他们的结果(下载的数据)放入另一个队列中。其他工作人员可以使用此队列进一步处理数据等等。

标签: python multithreading celery


【解决方案1】:

不!拜托,看在你的上帝或聪明的设计师的份上,不要那样做!不要不断地创建/产生/任何线程并尝试对它们进行微观管理。线程池 - 在启动时创建一些线程并将它们传递给生产者-消费者队列以等待代表这些 HTTP 任务的类实例。

【讨论】:

    【解决方案2】:

    您应该使用Queue.Queue。为每个系列创建一个队列,并在该队列上侦听一个线程。每次您需要阅读一个系列时,将一个请求放入队列中。线程等待队列中的项,每收到一项,就读取数据。

    【讨论】:

      【解决方案3】:

      如果您只是在每次查询返回时重新查询 API,您可以使用的另一个选项是异步框架,例如 Twisted (Their tutorial on Threading)。我是一个相对的 Twisted 初学者,所以可能有比这更好的方法来让 Twisted 适应你的任务 -

      from twisted.internet import reactor, defer
      def simple_task():
          status = query_your_api()
          return status
      
      def repeating_call(status):
          print(status)
          d = threads.deferToThread(simple_task)
          d.addCallback(repeating_call)
      
      data_series = [data1, data2, data3]
      for data in data_series:
          repeating_call('starting everything up')
      
      reactor.run()
      

      【讨论】:

        猜你喜欢
        • 2013-09-21
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多