Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在线程之间共享一个值并通知消费线程设置了一个新值_Python_Multithreading_Multiprocessing_Python Multiprocessing - Fatal编程技术网

Python 如何在线程之间共享一个值并通知消费线程设置了一个新值

Python 如何在线程之间共享一个值并通知消费线程设置了一个新值,python,multithreading,multiprocessing,python-multiprocessing,Python,Multithreading,Multiprocessing,Python Multiprocessing,对我来说,一个相当常见的情况是定期更新一个值,比如说每30秒更新一次。例如,此值在网站上可用 我想获取这个值(使用阅读器),转换它(使用转换器),然后发布结果,比如说在另一个网站上(使用出版商) 源和目标有时都不可用,我只对新值和超时感兴趣 我当前的方法是使用一个队列处理我的值,另一个队列处理我的结果。读卡器、转换器和发布器都是使用多处理的独立“线程” 这样做的好处是,可以允许每个步骤“挂起”一段时间,下一步可以使用带有超时的get来实现一些默认操作,以防队列中没有有效消息 这种方法的缺点是,当

对我来说,一个相当常见的情况是定期更新一个值,比如说每30秒更新一次。例如,此值在网站上可用

我想获取这个值(使用阅读器),转换它(使用转换器),然后发布结果,比如说在另一个网站上(使用出版商)

源和目标有时都不可用,我只对新值和超时感兴趣

我当前的方法是使用一个队列处理我的值,另一个队列处理我的结果。读卡器、转换器和发布器都是使用多处理的独立“线程”

这样做的好处是,可以允许每个步骤“挂起”一段时间,下一步可以使用带有超时的get来实现一些默认操作,以防队列中没有有效消息

这种方法的缺点是,当转换器或发布程序暂停时,我将保留所有以前的值并将结果放入队列中。在最坏的情况下,发布服务器出现不可恢复的错误,整个工具的内存不足

此问题的一个可能解决方案是将队列大小限制为1,使用非阻塞put,并通过丢弃当前值并重新放置新值来处理队列完全异常。对于这样一个简单的操作,这是相当多的代码,并且清楚地表明队列不是适合该作业的工具

我可以使用多处理原语编写我自己的类来获得我想要的行为,但这对我来说是一种非常常见的情况,所以我认为其他人也是如此,我觉得应该有一个“正确”的解决方案

简言之,是否有具有以下接口的标准threadsafe类

class Updatable():
    def put(value):
        #store value, overwriting existing

    def get(timeout):
        #blocking, raises Exception when timeout is set and exceeded
        return value
编辑:我当前使用多处理的实现

import multiprocessing
from time import sleep

class Updatable():
    def __init__(self):
        self.manager = multiprocessing.Manager()
        self.ns = self.manager.Namespace()
        self.updated = self.manager.Event()

    def get(self, timeout=None):
        self.updated.wait(timeout)
        self.updated.clear()
        return self.ns.x

    def put(self, item):
        self.ns.x = item
        self.updated.set()


def consumer(updatable):
    print(updatable.get())  # expect 1
    sleep(1)
    print(updatable.get())  # expect "2"
    sleep(1)
    print(updatable.get())  # expect {3}, after 2 sec
    sleep(1)
    print(updatable.get())  # expect [4]
    sleep(2)
    print(updatable.get())  # expect 6
    sleep(1)

def producer():
    sleep(.5)  # make output more stable, by giving both sides 0.5 sec to process
    updatable.put(1)
    sleep(1)
    updatable.put("2")
    sleep(2)
    updatable.put({3})
    sleep(1)
    updatable.put([4])
    sleep(1)
    updatable.put(5,)  # will never be consumed 
    sleep(1)
    updatable.put(6)

if __name__ == '__main__':
    updatable = Updatable()
    p = multiprocessing.Process(target=consumer, args=(updatable,))
    p.start()
    producer()

您说您在多处理模块中使用线程。在Python中,线程和多处理(行为)是非常不同的,到底是什么?我使用多处理作为抽象线程概念的实现。我应该注意,使用多处理不是我的要求,因此如果使用线程模块有更好的解决方案,我也感兴趣如果你不需要多处理,不要用它。
Threading
模块使用几乎相同的语法,使用起来更简单。我真的不明白为什么您需要一个队列,难道您不能将最后一个值存储在本地并在不可用的情况下处理异常吗?你能提供一个示例代码来帮助我理解吗?老实说,我之所以在线程上使用多处理是因为队列的实现。通过队列传递dict。队列传递引用,而通过多处理传递dict。队列传递副本。在两个线程中使用此引用花费的时间比我愿意承认的要多。您说您在多处理模块中使用线程。在Python中,线程和多处理(行为)是非常不同的,到底是什么?我使用多处理作为抽象线程概念的实现。我应该注意,使用多处理不是我的要求,因此如果使用线程模块有更好的解决方案,我也感兴趣如果你不需要多处理,不要用它。
Threading
模块使用几乎相同的语法,使用起来更简单。我真的不明白为什么您需要一个队列,难道您不能将最后一个值存储在本地并在不可用的情况下处理异常吗?你能提供一个示例代码来帮助我理解吗?老实说,我之所以在线程上使用多处理是因为队列的实现。通过队列传递dict。队列传递引用,而通过多处理传递dict。队列传递副本。在两个线程中使用此引用花费的时间比我愿意承认的要多。