Python中的多线程(我的代码是正确的)

时间:2015-03-26 21:33:50

标签: python multithreading

我正在测试以下代码,我想确定它是否正确:

from threading import Thread
import cPickle

def get_user(start, end):
    global users, vusers
    for j in range(start,end):
        if str(users[j]).find('@N') != -1:
            vusers.append(users[j])


if __name__ == '__main__':
    users = cPickle.load(open('nsid.dmp', 'r'))
    vusers = []
    jobs = [Thread(target=get_user, args=(0,1839))\
        ,Thread(target=get_user, args=(1840,3679))\
        ,Thread(target=get_user, args=(3680,5519))\
        ,Thread(target=get_user, args=(5520,7359))\
        ,Thread(target=get_user, args=(7360,9199))\
        ,Thread(target=get_user, args=(9200,11039))\
        ,Thread(target=get_user, args=(11040,12879))\
        ,Thread(target=get_user, args=(12880,14719))\
        ,Thread(target=get_user, args=(14720,16559))\
        ,Thread(target=get_user, args=(16560,18399))\
        ,Thread(target=get_user, args=(18400,20239))\
        ,Thread(target=get_user, args=(20240,20079))\
        ,Thread(target=get_user, args=(22080,23919))\
        ,Thread(target=get_user, args=(23920,25759))\
        ,Thread(target=get_user, args=(25760,27599))\
        ,Thread(target=get_user, args=(27600,29439))]
    for jb in jobs:
        jb.start()  
    for jb in jobs:
        jb.join()
    vusers = list(set(vusers))
    out = open('validu.dmp', 'w')
    cPickle.dump(vusers, out)
    out.close()

所以我要做的是与不同范围的函数get_user并行运行。当然,函数get_user比这更复杂,还有许多其他条件需要检查,但是当我运行代码时,我看不到时间效率更高。我的代码有什么问题,是否是编写多线程函数的正确方法?如果没有,我怎么能让它并行运行?

2 个答案:

答案 0 :(得分:1)

由于GIL,这不会并行运行。我甚至不确定它是否会同时运行,因为每个目标函数似乎都没有释放GIL(即没有系统调用等)。

要绕过GIL,您将使用多处理模块。当您使用多处理时,共享状态要困难得多,因此您需要重新组织代码以收集程序主线程中每个子进程返回的答案。

答案 1 :(得分:0)

我认为出于性能原因,你想要众多。如果是这种情况你应该使用Process而不是Thread,你可以阅读更多关于python Theads here的限制。

我真的很喜欢multiprocess.Pool,它引用了multiprocess.Process。它允许您为它们启动一些固定数量的进程和队列任务。以下是使用pool.apply_async的示例,但我也会查看pool.mappool.map_async

from multiprocessing import Pool

def get_user(users):
    return [u for u in users if 'N' in u]

def main(users):
    vusers = []
    results = []

    N = 2
    chunk = 200

    pool = Pool(N)
    for i in range(0, len(users), chunk):
        r = pool.apply_async(get_user, args=(users[i:i + chunk],))
        results.append(r)

    pool.close()
    pool.join()

    for r in results:
        vusers.extend(r.get())

    return vusers

if __name__ == '__main__':
    import random
    import string
    users = [random.sample(string.ascii_uppercase, 5) for i in range(10000)]
    vusers = main(users)