Skip to main content
 首页 » 编程设计

python之多线程迭代器

2024年10月17日32zhenyulu

我需要实现 Iterator返回两个值(到目前为止没有异常),但这些值需要并行连续计算/生成,即使未请求迭代器也是如此。

这里是一个例子来解释我需要什么。

def GenerateValues() 
    #I do the math for value1 in the first thread 
    #I do the math for value2 in the second thread 
    return value1 value2 
 
def myIterator() 
    while 1: 
        yield GenerateValues() 

在这种情况下,value1和 value2仅在调用函数 myIterator 时并行计算/生成。但在我的问题中,计算/生成 value1 需要很长时间和 value2 , 但它也需要很长时间来处理 value1和 value2 .所以当我的软件正在处理value1和 value2 , 我希望它并行计算新的 value1和新value2 .

所以它会是这样的:

def GenerateValues() 
    #If value1 and value 2 are not computed, then wait. 
 
    #I do the math for the new value1 in the first thread without blocking 
    #I do the math for the new value2 in the second thread without blocking 
    return value1 value2 
 
def myIterator() 
    while 1: 
        yield GenerateValues() 

有了这样的配置,新的value1和新value2在 value1 时计算/生成和 value2返回进行处理。

  • 够清楚了吗?
  • 如果是,我该如何进行同步?

预先感谢您的帮助!

PS:我需要 while 1 ,这一点无需评论。

请您参考如下方法:

不确定我是否完全理解你想要做什么,如果你试图并行计算 value1 和 value2,你可以使用 multiprocessing 或 threading。如果任务受 CPU 限制,我建议使用 multiprocessing,以充分利用您的 CPU 通过使用子进程而不是线程来“回避”全局解释器锁 (GIL)。

这是一个使用多处理的相当直接的例子:

from multiprocessing import Queue, Process 
 
def cal_value1(queue): 
    # do the job 
    queue.put({'value1': value1}) 
 
def cal_value2(queue): 
    # do the job 
    queue.put({'value2': value2}) 
 
def GenerateValues() 
    #If value1 and value 2 are not computed, then wait. 
    queue = Queue() #  
    process_1 = Process(target=cal_value1, args=(queue, )) 
    process_2 = Process(target=cal_value2, args=(queue, )) 
    process_1.start() 
    process_2.start()  # start both processes 
    process_1.join() 
    process_2.join()  # wait for both to finish 
 
    result = queue.get() 
    result.update(queue.get()) # get results 
 
    return result['value1'], result['value2'] 

附言您可以轻松地使用 threading.Thread 和 Queue.Queue 来替换 multiprocessing.Process 和 multiprocessing.Queue 如果你想。

编辑: 现在让 cal_value1 和 cal_value2 长时间运行的进程,您可能希望在脚本的开头启动这 2 个进程。

from multiprocessing import Queue, Process 
 
def cal_value1(tasks, results): 
    while True: 
        task = tasks.get() # this will block until a new task coming in 
        # calculate value1 
        results.put({'value1': value1}) 
 
def cal_value2(tasks, results): 
    while True: 
        task = tasks.get() # this will block until a new task coming in 
        # calculate value2 
        results.put({'value2': value2}) 
 
def main(): 
    cal_value1_tasks, cal_value2_tasks, results = Queue(), Queue(), Queue() 
    process_1 = Process(target=cal_value1, args=(cal_value1_tasks, results, )) 
    process_2 = Process(target=cal_value2, args=(cal_value2_tasks, results, )) 
    process_1.start() 
    process_2.start() 
    cal_value1_tasks.put('cal_value1') 
    cal_value2_tasks.put('cal_value2') # Start to calculate the first pair 
    values = GenerateValues(cal_value1_tasks, cal_value2_tasks, results) 
 
def GenerateValues(cal_value1_tasks, cal_value2_tasks, results): 
    values = results.get() # get results 
    values.update(queue.get()) # notice that it'll block until both value1 and value 2 calculated 
    cal_value1_tasks.put('cal_value1') 
    cal_value2_tasks.put('cal_value2') # before returning, start to calculate the next round of value1 and value2 
    return values['value1'], values['value2]