在__init__类中初始化多进程是否正确?

时间:2018-10-01 07:52:29

标签: python multiprocessing thread-safety

from multiprocessing.dummy import Pool as ThreadPool
class TSNew:
    def __init__(self):
        self.redis_client = redis.StrictRedis(host="172.17.31.147", port=4401, db=0)
        self.global_switch = 0
        self.pool = ThreadPool(40) # init pool
        self.dnn_model = None
        self.nnf = None
        self.md5sum_nnf = "initialize"
        self.thread = threading.Thread(target=self.load_model_item)
        self.ts_picked_ids = None
        self.thread.start()

        self.memory = deque(maxlen=3000)
        self.process = threading.Thread(target=self.process_user_dict)
        self.process.start()

    def load_model_item(self):
        '''
        code
        '''
    def predict_memcache(self,user_dict):
        '''
        code
        '''
    def process_user_dict(self):
        while True:
            '''
            code to generate user_dicts which is a list 
            '''
            results = self.pool.map(self.predict_memcache, user_dicts)
            '''
            code
            '''
TSNew_ = TSNew()

def get_user_result():
    logging.info("----------------come in ------------------")
    if request.method == 'POST':
        user_dict_json = request.get_data()# userid
        if user_dict_json == '' or user_dict_json is None:
            logging.info("----------------user_dict_json is ''------------------")
            return ''
        try:
            user_dict = json.loads(user_dict_json)
        except:
            logging.info("json load error, pass")
            return ''
        TSNew_.memory.append(user_dict)
        logging.info('add to deque TSNew_.memory size: %d  PID: %d', len(TSNew_.memory), os.getpid())
        logging.info("add to deque userid: %s, nation: %s \n",user_dict['user_id'],  user_dict['user_country'])
        return 'SUCCESS\n'


@app.route('/', methods=['POST'])
def get_ts_gbdt_id():
    return get_user_result()

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=4444)

我在类__init__中创建了一个多线程池,并使用了self.pool 来映射predict_memcache的功能。 我有两个疑问: (a)我应该在__init__中初始化池还是在

之前将其初始化?
results = self.pool.map(self.predict_memcache, user_dicts)

(b)由于池是多线程操作,并且在process_user_dict线程中执行,因此是否存在任何隐藏的错误? 谢谢。

1 个答案:

答案 0 :(得分:0)

问题(a):

这取决于。如果您需要多次运行process_user_dict,则有必要在构造函数中启动池并保持其运行。创建线程池总是会带来一些开销,并且通过在调用process_user_dict之间保持线程池处于活动状态,您可以避免该额外开销。

如果只想处理一组输入,也可以在process_user_dict内创建池。但是可能不早于results = self.pool.map(self.predict_memcache, user_dicts),因为那样会为周围的while循环的每次迭代创建一个池。

在您的特定情况下,它没有任何区别。您可以在模块级别创建TSNew_对象,以便在您的应用运行时使该对象保持活动状态(并带有线程池);来自同一TSNew实例的同一线程池在app.run()的生存期内用于处理所有请求。 由于您似乎将self.process = threading.Thread(target=self.process_user_dict)的结构用作self.memory上的某种侦听器,因此在构造函数中创建池在功能上等同于在process_user_dict内创建池(但在循环)。

问题(b):

从技术上讲,在线程内部创建线程时,默认情况下没有隐藏的错误。最后,任何其他线程的最终父代始终是MainThread,它是为Python解释器的每个实例隐式创建的。基本上,每次在Python程序中创建一个线程时,都会在一个线程中创建一个线程。

实际上,您的代码甚至没有在线程内部创建线程。您的self.poolMainThread内部创建。通过self.pool = ThreadPool(40)实例化池时,它将创建所需数量(40)的工作线程,外加一个工作处理器线程,一个任务处理器线程和一个结果处理器线程。所有这些都是MainThread的子线程。您在self.process下对线程内的池所做的所有工作就是调用其map方法来为其分配任务。

但是,我在这里并没有真正了解您对self.process所做的工作。 猜一猜,我想您想在process_user_dict中启动循环以充当self.memory上的侦听器,以便该池一开始就开始处理user_dict显示在deque中的self.memory中。从我看到您在get_user_result中所做的事情来看,每个请求似乎可以得到一个user_dict。我了解您可能会在这些指令中传递并发用户会话,但是您真的看到process_user_dict在无限循环中的好处,而不是在TSNew_.process_user_dict()之后简单地调用TSNew_.memory.append(user_dict)吗?您甚至可以完全省略self.memory并将字典直接传递给process_user_dict,除非我错过了您没有向我们展示的内容。