Python的threading和multiprocessing模块分析
发布时间:2021-12-14 12:59:35 所属栏目:教程 来源:互联网
导读:前言 这两天为了做一个小项目,研究了一下Python的并发编程,所谓并发无非多线程和多进程,最初找到的是threading模块,因为印象中线程轻量...,切换快...,可共享进程资源...等等,但是没想到这里水很深,进而找到了更好的替代品multiprocessing模块。下面
前言 这两天为了做一个小项目,研究了一下Python的并发编程,所谓并发无非多线程和多进程,最初找到的是threading模块,因为印象中线程“轻量...”,“切换快...”,“可共享进程资源...”等等,但是没想到这里水很深,进而找到了更好的替代品multiprocessing模块。下面会讲一些使用中的经验。 后面出现的代码都在Ubuntu10.04 + python2.6.5的环境下测试通过。 一、使用threading模块创建线程 1、三种线程创建方式 (1)传入一个函数 这种方式是最基本的,即调用threading中的Thread类的构造函数,然后指定参数target=func,再使用返回的Thread的实例调用start()方法,即开始运行该线程,该线程将执行函数func,当然,如果func需要参数,可以在Thread的构造函数中传入参数args=(...)。示例代码如下: #!/usr/bin/python #-*-coding:utf-8-*- import threading #用于线程执行的函数 def counter(n): cnt = 0; for i in xrange(n): for j in xrange(i): cnt += j; print cnt; if __name__ == '__main__': #初始化一个线程对象,传入函数counter,及其参数1000 th = threading.Thread(target=counter, args=(1000,)); #启动线程 th.start(); #主线程阻塞等待子线程结束 th.join(); 这个例子关键的一句是apply(self.func, self.args); 这里使用初始化时传入的函数对象及其参数来进行一次调用。 (3)继承Thread类 这种方式通过继承Thread类,并重载其run方法,来实现自定义的线程行为,示例代码如下: #!/usr/bin/python #-*-coding:utf-8-*- import threading, time, random def counter(): cnt = 0; for i in xrange(10000): for j in xrange(i): cnt += j; class SubThread(threading.Thread): def __init__(self, name): threading.Thread.__init__(self, name=name); def run(self): i = 0; while i < 4: print self.name,'counting...n'; counter(); print self.name,'finishn'; i += 1; if __name__ == '__main__': th = SubThread('thread-1'); th.start(); th.join(); print 'all done'; 这个例子定义了一个SubThread类,它继承了Thread类,并重载了run方法,在方法中调用counter4次并打印一些信息,可以看到这种方式比较直观。在构造函数中要记得先调用父类的构造函数进行初始化。 2、python多线程的限制 python多线程有个讨厌的限制,全局解释器锁(global interpreter lock),这个锁的意思是任一时间只能有一个线程使用解释器,跟单cpu跑多个程序一个意思,大家都是轮着用的,这叫“并发”,不是“并行”。手册上的解释是为了保证对象模型的正确性!这个锁造成的困扰是如果有一个计算密集型的线程占着cpu,其他的线程都得等着....,试想你的多个线程中有这么一个线程,得多悲剧,多线程生生被搞成串行;当然这个模块也不是毫无用处,手册上又说了:当用于IO密集型任务时,IO期间线程会释放解释器,这样别的线程就有机会使用解释器了!所以是否使用这个模块需要考虑面对的任务类型。 (编辑:我爱故事小小网_铜陵站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |