首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > perl python >

python的threading跟multiprocessing模块初探

2012-11-19 
python的threading和multiprocessing模块初探前言 这两天为了做一个小项目,研究了一下python的并发编程,所

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 time, multiprocessing, signal, threading, random, time, Queueclass Master(multiprocessing.Process):    def __init__(self):        super(Master,self).__init__();        signal.signal(signal.SIGTERM, self.handler);#这个变量要传入线程用于控制线程运行,为什么用dict?充分利用线程间共享资源的特点#因为可变对象按引用传递,标量是传值的,不信写成self.live = true试试        self.live = {'stat':True};                       def handler(self, signum, frame):        print 'signal:',signum;        self.live['stat'] = 0;                                   #置这个变量为0,通知子线程可以“收工”了    def run(self):        print 'PID:',self.pid;             cond = threading.Condition(threading.Lock());            #创建一个condition对象,用于子线程交互        q = Queue.Queue();                                       #一个队列        sender = Sender(cond, self.live, q);                     #传入共享资源        geter = Geter(cond, self.live, q);        sender.start();                                          #启动线程        geter.start();        signal.pause();                                          #主线程睡眠并等待信号        while threading.activeCount()-1:                         #主线程收到信号并被唤醒后,检查还有多少线程活着(除掉自己)            time.sleep(2);                                       #再睡眠等待,确保子线程都安全的结束            print 'checking live', threading.activeCount();        print 'mater gone';class Sender(threading.Thread):    def __init__(self, cond, live, queue):        super(Sender, self).__init__(name='sender');        self.cond = cond;        self.queue = queue;        self.live = live    def run(self):        cond = self.cond;        while self.live['stat']:                                 #检查这个进程内的“全局”变量,为真就继续运行            cond.acquire();                                      #获得锁,以便控制队列            i = random.randint(0,100);            self.queue.put(i,False);            if not self.queue.full():                print 'sender add:',i;            cond.notify();                                       #唤醒等待锁的其他线程            cond.release();                                      #释放锁            time.sleep(random.randint(1,3));        print 'sender done'class Geter(threading.Thread):    def __init__(self, cond, live, queue):        super(Geter, self).__init__(name='geter');        self.cond = cond;        self.queue = queue;        self.live = live    def run(self):        cond = self.cond;        while self.live['stat']:            cond.acquire();            if not self.queue.empty():                i = self.queue.get();                print 'geter get:',i;            cond.wait(3);            cond.release();            time.sleep(random.randint(1,3));        print 'geter done'if __name__ == '__main__':    master = Master();    master.start();                                              #启动子进程


需要注意的地方是,在Master的run方法中sender.start()和geter.start()之后,按常理应该接着调用sender.join()和geter.join(),让主线程等待子线程结束,前面说的join的陷阱就在这里,join将主线程阻塞(blocking)住了,主线程无法再捕捉信号,刚开始研究这块时还以为信号处理函数写错了。网上讨论比较少,这里说的比较清楚http://stackoverflow.com/questions/631441/interruptible-thread-join-in-python,http://www.gossamer-threads.com/lists/python/python/541403参考:《python核心编程》《python manual》 






热点排行