如何解决ThreadPoolExecutor是否在两次迭代之间保留线程本地数据?
我注意到,如果我使用ThreadPoolExecutor(max_workers = 5)运行一次函数10次,则在两次迭代之间将维护线程本地数据,就像重新使用线程一样。我有以下非常基本的代码要测试:
import time
import uuid
import threading
import concurrent.futures
thread_data = threading.local()
def conc_func(i):
if not hasattr(thread_data,'x'):
thread_data.x = uuid.uuid4()
print('Setting Thread Data: ',end='')
else:
print('Reading Thread Data: ',end='')
print(thread_data.x)
time.sleep(1)
def conc_pool():
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
_ = executor.map(conc_func,range(10))
if __name__ == '__main__':
conc_pool()
如果运行此代码,则会得到以下输出
Setting Thread Data: e0101c90-1de7-4c5c-8358-05c6e5b5c89f
Setting Thread Data: 34d1c796-d9e0-4000-a560-2b0d0da47fb4
Setting Thread Data: 2a62e83e-0945-40d4-8af5-e5e77ee9531f
Setting Thread Data: b9bf8871-ea9d-4dca-88d2-c8916ff47e5d
Setting Thread Data: 961a7725-9ebb-4711-81c9-253ddc1c9c80
Reading Thread Data: e0101c90-1de7-4c5c-8358-05c6e5b5c89f
Reading Thread Data: 34d1c796-d9e0-4000-a560-2b0d0da47fb4
Reading Thread Data: 2a62e83e-0945-40d4-8af5-e5e77ee9531f
Reading Thread Data: b9bf8871-ea9d-4dca-88d2-c8916ff47e5d
Reading Thread Data: 961a7725-9ebb-4711-81c9-253ddc1c9c80
如您所见,只有5个唯一的UUID(与唯一工作程序的数量相同)。因为我最多分配5个工作程序,但传递带有10个元素的可迭代对象,所以每个工作程序处理两次迭代。但是,令我惊讶的是,线程本地数据实例在迭代之间共享,而我希望它在每次运行时都是CLEAN。
有没有一种方法可以自动清理Local-Thread Data实例,还是应该在迭代结束时自行清理呢?
解决方法
线程池重用线程,这就是重点。任何线程本地数据都将附加到线程。只要它是活动的,它将一直保留在线程中,并且不会自行清理。您必须手动执行。
话虽如此,我的建议是完全避免线程本地存储。我还没有看到有必要并且您不能简单地将数据作为参数传递的情况。也许除外,除非您已经处理了设计不良的代码。缺点是它很难调试并且是一个很强的依赖性,例如如果您想切换为单线程异步代码,那么您将再次遇到问题,就像现在重用线程而不是每次都生成新线程一样。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。