【问题标题】:How to know if a particular task inside a queue is complete?如何知道队列中的特定任务是否完成?
【发布时间】:2012-08-03 15:41:07
【问题描述】:

我对 python 队列有疑问。

我写了一个线程类,它的run()方法执行队列。

  import threading
  import Queue

  def AThread(threading.Thread):
     def __init__(self,arg1):
         self.file_resource=arg1
         threading.Thread.__init__(self)
         self.queue=Queue.Queue()

     def __myTask(self):
         self.file_resource.write()
         ''' Method that will access a common resource
          Needs to be synchronized.
          Returns a Boolean based on the outcome
         '''

     def run():
         while True:
             cmd=self.queue.get()
             #cmd is actually a call to method
             exec("self.__"+cmd)
             self.queue.task_done()


 #The problem i have here is while invoking the thread
 a=AThread()
 a.queue.put("myTask()")
 print "Hai"

同一个 AThread 实例 (a=AThread()) 会将任务从不同位置加载到队列中。

因此底部的 print 语句应该等待通过上面的语句添加到队列中的任务,并等待一个确定的时间,并在执行任务后接收返回的值。

有没有一种简单的方法来实现这一点?我对此进行了很多搜索,请查看此代码并提供建议。

以及为什么python的获取和释放锁不在类的实例上。在上述场景中,AThread 的实例 a 和 b 不需要同步,但是当应用获取和释放锁时,myTask 会为 a 和 b 的两个实例同步运行。

请提供建议。

【问题讨论】:

  • 为什么每个线程都有一个队列?
  • 我现在已经修改了代码。 a=Athread("a.txt") 等待 b=AThread("b.txt") 是不合适的,因为他们对 myTask 方法的调用将在 2 个不同的文件上。因此 Athread("a.txt") 只会被调用一次,所有其他对 myTask 的调用都将进入队列。
  • 不多使用线程,但通常队列是全局的,并保存要完成的任务。有一个线程池(线程队列)保存线程。线程管理器将循环直到任务队列不为空 - 它会唤醒,从 task_queue 中拉出一个任务,从线程池中拉出一个线程。将任务分配给线程。去睡觉。如果线程池中不存在线程,它将休眠并重试。线程本身 - 执行并返回结果后会将其自身添加到线程池中。线程将彼此独立工作,但在所有任务完成之前程序不会退出。

标签: python multithreading


【解决方案1】:

您可以采取多种方法,具体取决于您的问题的具体情况。

如果您的print "Hai" 只需要在 myTask 完成后发生,您可以将其放入一个任务中,并让 myTask 在完成时将该任务放入队列中。 (如果你是 CS 理论类的人,你可以认为这类似于 continuation-passing 风格)。

如果您的 print "Hai" 对多个任务有更复杂的依赖,您可能会考虑期货或承诺。

您可以进入基于 Actor 的并发世界,在这种情况下,可能会有一个同步消息发送方法或多或少地完成您想要的操作。

如果您不想使用期货或承诺,您可以手动实现类似的事情,方法是引入条件变量。在 myTask 启动之前设置条件变量并将其传递给 myTask,然后等待它被清除。随着程序的增长,您必须非常小心,并不断重新考虑您的锁定策略,以确保它保持简单和易于理解 - 这就是造成困难并发错误的原因。

获得所需内容的最小明智步骤可能是提供 Queue.put() 的阻塞版本,它执行条件变量的事情。确保您考虑是否要阻塞直到队列为空,或者直到您放入队列的内容从队列中删除,或者直到您放入队列的内容完成处理。然后确保您实施您在考虑时决定实施的事情。

【讨论】:

  • 我只是想知道,我从队列中获得的实际好处是什么。我觉得我可以通过 python 列表来实现这一点。如果提供了 queue.iscomplete(task) return bool 方法,它可能会很有用。
  • queue.put() 线程安全吗?是 list.append() 吗?我不知道这两个问题的答案,但如果第一个是肯定的,第二个不是,那么这就是一个好处。另一个好处是性能方面:当您在一端添加东西并从另一端取出东西时,队列应该表现良好,但是如果您为此使用列表,则会进行大量复制(要么移动所有现有的插入时向前移动元素或在删除时向后移动所有元素)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多