【问题标题】:Is there any replacement for empty while loops?空的while循环有什么替代品吗?
【发布时间】:2018-04-22 15:28:22
【问题描述】:

我经常使用空的 while 循环,例如: 我有一个在后台运行的线程,它将在 5 秒内更改一个名为“a”的值。但是,我同时使用了不同的函数,我想让第二个函数知道值发生了变化,所以我一直做的是:

import threading, time
class example:
       def __init__(self):
          self.a = 0


       def valchange(self):
          time.sleep(5)
          self.a += 1
          time.sleep(1)
          print("im changing the a value to " + str(self.a))
          print("those print commands needs to run after notifier stopped his while and started printing")

def notifier(exam :example, num :int):
    while(exam.a != num):
        pass
    print("it changed to " + str(num))


exa = example()
i = 1
while(i <= 16):
    temp= threading.Thread(target=notifier, args=(exa, i, ))
    temp.start()
    i += 3
i = 1
while(i <= 16):
    exa.valchange()
    i += 1

值得一提的是,该示例不能使用等待和设置事件,因为没有指示何时需要运行设置,以及在后台运行的线程数,甚至是什么数字将有一个线程等待他们更改。 而且你也不能使用 join 因为改变'a'不是要打印的标志,只有条件才是标志。 由于最后一个原因,异步和选择也无法帮助我。

有什么方法可以创建一些东西,让程序停止运行,直到条件变为真?你可以用任何你想要的编程语言来提供你的解决方案,但我主要使用的是 python 3。

编辑:请记住,我需要它来适应各种情况。而我的代码示例 - 只是一个示例,所以如果在那里工作,它不一定会在不同的条件下工作。

提前非常感谢你:)

想法:

wait(a == 5) // will do nothing until a == 5

【问题讨论】:

  • 如果您的 while 循环无限期地什么都不做,那么任何其他可能导致循环中断的代码是如何执行的?您的帖子的答案可能取决于您如何执行此操作。穿线?多处理?有很多方法可以让并行线程/进程/任何东西一起玩得很好,但一些解决方案将特定于某些模块。例如,threading.Lock 仅在您使用线程时才有用。
  • 上述线程的代码在哪里?
  • @hspandher 现在好点了吗?

标签: python while-loop conditional-statements wait


【解决方案1】:

如果您正在等待某些系统操作完成,则需要使用selectepoll 系统调用。如果您正在等待某个 IO 事件,那么您可以使用asyncio(前提是您的 Python 版本 > 3.3),否则您可以考虑使用twisted

如果您正在执行一些 CPU 密集型操作,您需要考虑多个进程或线程,只有这样您才能有效地进行任何此类监控。让 while 循环无限运行而没有任何中断是等待发生的灾难。

【讨论】:

  • 您能否提供更多详细信息,或者如何使用它的示例。非常感谢:)
  • @user6516763 您没有提供有关您在等待什么的详细信息。
【解决方案2】:

如果您的线程只更改一次a 的值,在其生命周期结束时,您可以使用.join() 等待线程终止。

import threading
import time

class example:
   def __init__(self):
      self.a = 0
      self.temp = threading.Thread(target=self.valchange)
      self.temp.start()
      self.notifier()

   def valchange(self):
      time.sleep(5)
      self.a = 1

   def notifier(self):
      self.temp.join()
      print("the value of a has changed")

example()

如果线程可能在其生命周期的任何时候更改a 的值,那么您可以使用threading 模块的更通用的控制流对象之一来协调执行。例如,Event 对象。

import threading
import time

class example:
   def __init__(self):
      self.a = 0
      self.event = threading.Event()
      temp = threading.Thread(target=self.valchange)
      temp.start()
      self.notifier()

   def valchange(self):
      time.sleep(5)
      self.a = 1
      self.event.set()

   def notifier(self):
      self.event.wait()
      print("the value of a has changed")

example()

这种Event 方法的一个缺点是线程目标必须在更改a 的值时显式调用set(),如果您在代码中多次更改a,这可能会令人恼火。您可以使用属性将其自动化:

import threading
import time

class example(object):
    def __init__(self):
        self._a = 0
        self._a_event = threading.Event()

        temp = threading.Thread(target=self.valchange)
        temp.start()
        self.notifier()

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a = value
        self._a_event.set()

    def valchange(self):
        time.sleep(5)
        self.a = 1

    def notifier(self):
        self._a_event.wait()
        print("the value of a has changed")

example()

现在valchange 在设置a 的值后不需要做任何特别的事情。

【讨论】:

  • 首先,非常感谢您提供的令人难以置信的帮助,感谢您浪费时间帮助我,我真的很感激 :D 但实际上,我编辑了我的问题,并添加了一个这次的代码有点不同,稍微复杂一点,用你的方法也无法得到我想要的答案..
  • "没有迹象表明 [...] 哪些数字会有线程等待它们更改" 嗯,这确实很棘手...
【解决方案3】:

您所描述的是自旋锁,可能没问题,具体取决于您的用例。

另一种方法是让您等待的代码在达到特定条件时给您回电。这将需要一个异步框架,例如 https://docs.python.org/3/library/asyncio-task.html

这些文档中有一些很好的简单示例,所以我不会在此处粘贴它们来侮辱您的智慧。

【讨论】:

    猜你喜欢
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    相关资源
    最近更新 更多