先说结论:
在使用多线程时,不要使用threadpool,应该使用threading, 尤其是数据量大的情况。因为threadpool会导致严重的内存占用问题!
对比threading和threadpool的内存占用
# coding=utf-8 import time import os import psutil import json import threadpool import threading class TEST(object): # 获取数据,使用yield, 每次返回一个len=10的list, list中的每一项是一个线程的数据 def get_data(self): multi_list = list() for i in range(100): data = "abcdefg" * 100000 multi_list.append(data) if len(multi_list) % 10 == 0: yield multi_list multi_list = list() # 测试函数 def test(self): for data in self.get_data(): mem = psutil.Process(os.getpid()).memory_info().rss print "[test] mem %s" % mem # 打印内存占用情况 self.deal_threadpool(data) # 使用threadpool # self.deal_multi_thread(data) # 使用threading # 待对比方法,threadpool def deal_threadpool(self, data_list): pool = threadpool.ThreadPool(10) requests = threadpool.makeRequests(self.sub_task, data_list) [pool.putRequest(req) for req in requests] pool.wait() # 待对比方法,threading def deal_multi_thread(self, data_list): threads = list() for data in data_list: threads.append(threading.Thread(target=self.sub_task, args=(data,))) for t in threads: t.start() for t in threads: t.join() def sub_task(self, data): return if __name__ == "__main__": mem = psutil.Process(os.getpid()).memory_info().rss print "[main] mem %s" % mem obj = TEST() obj.test() mem = psutil.Process(os.getpid()).memory_info().rss print "[main] mem %s" % mem
结果:
1. 使用threadpool时
[main] mem 9760768 [test] mem 16764928 [test] mem 23924736 [test] mem 26820608 [test] mem 29720576 [test] mem 31911936 [test] mem 34795520 [test] mem 36978688 [test] mem 39161856 [test] mem 41340928 [test] mem 43524096 [main] mem 43606016
2. 使用threading时
[main] mem 9760768 [test] mem 16764928 [test] mem 23838720 [test] mem 16969728 [test] mem 23838720 [test] mem 16969728 [test] mem 23838720 [test] mem 16973824 [test] mem 23842816 [test] mem 16973824 [test] mem 23842816 [main] mem 16973824
对比可以看出,
使用threading时,每次线程退出可以正确的释放内存,内存占用的最大值很稳定。
使用threadpool时,每次线程退出后内存都没有释放,而是一直累加。在我实际使用的过程中,从mongo获取了大量的数据,threadpool在处理过程中占用的内存高达50g,而使用threading后内存占用稳定在了1g.