python中实现多线程可以通过threading类。线程间同步则可以用queue类。至于python的进程间通信,暂时没有发现有类似linux ipc的模块可供使用,但是可以通过unix域套接字实现进程间通信。
1、用threading模块实现多线程
可以通过派生threading.Thread类来实现一个可独立控制的线程实例。用户需要(也只能)重写Thread类的__init__和run函数来实现自己的线程。线程类实例化后可以通过使用start函数使线程运行,该函数会在新开启的线程中调用run函数。这里需要注意的是,该类中只有run函数是出在独立的线程中运行的,其他控制函数都是处在调用者线程中执行的。其他线程可以通过调用Thread实例的join函数来阻塞自己等待线程运行结束。Thread类中name属性用来存放线程的名字。在python中主线程是一个名为“
main thread”的Thread实例。
1.1、Thread类中的函数
start():启动线程
。只能调用一次,否则会报错。该函数启动一个单独的线程运行run函数。
run():通过重写这个函数来实现用户函数在线程中的运行。也可以在类实例化的时候直接指定运行函数,那样的话可以不用重写这个函数,
join(timeout=None):调用这个函数的线程收到阻塞直到线程实例退出。timeout,一个浮点数,可以指定超时时间,单位秒。
name:存放线程的名字。可以更改,默认为Thread-n的格式。
ident:存放线程标识,一个整数。在线程结束后依然存在(直到线程资源被回收)
is_alive():判断线程是否存活。返回True或者False。调用模块函数 enumerate()可以得到所以存活的线程。
daemon:指定线程是否为守护线程
run():通过重写这个函数来实现用户函数在线程中的运行。也可以在类实例化的时候直接指定运行函数,那样的话可以不用重写这个函数,
join(timeout=None):调用这个函数的线程收到阻塞直到线程实例退出。timeout,一个浮点数,可以指定超时时间,单位秒。
name:存放线程的名字。可以更改,默认为Thread-n的格式。
ident:存放线程标识,一个整数。在线程结束后依然存在(直到线程资源被回收)
is_alive():判断线程是否存活。返回True或者False。调用模块函数 enumerate()可以得到所以存活的线程。
daemon:指定线程是否为守护线程
1.2、线程实例
import threading import Queue import time class mn_access(threading.Thread): def __init__(self,interval): threading.Thread.__init__(self) self.interval=interval self.thread_stop= False def run(self): #这个函数中存放用户自己的功能代码 i= 1; while not self.thread_stop: print( "thread%d %s: i am alive hehe %d" %(self.ident,self.name,i)) time.sleep(self.interval) i=i+ 1 def stop(self): self.thread_stop = True if __name__ == "__main__": mn=mn_access( 1) mn.start() #线程开始 time.sleep( 5) mn.stop()以上代码实现一个简单的线程实例,这段代码会生成一个线程并且周期性打印以证明自己存活。程序运行后打印:thread140109270083328 Thread-1: i am alive hehe 1thread140109270083328 Thread-1: i am alive hehe 2thread140109270083328 Thread-1: i am alive hehe 3thread140109270083328 Thread-1: i am alive hehe 4thread140109270083328 Thread-1: i am alive hehe 5
2、Queue模块:线程间的消息队列
queue模块用来实现消息队列功能,可以实现线程间安全的消息交换。各个线程可以通过调用消息队列实例对消息队列进行操纵。
2.1、queue对象
queue对象实现一个fifo队列(其他的还有lifo、priority队列,这里不再介绍)。queue只有qsize一个构造参数,用来指定队列容量,指定为0的时候代表容量无限。主要有以下成员函数:
Queue.
qsize
(
):返回消息队列的当前空间。返回的值不一定可靠。
Queue.
empty
(
):判断消息队列是否为空,返回True或False。同样不可靠。
Queue.
full
(
):类似上边,判断消息队列是否满
Queue.
put
(
item
,
block=True
,
timeout=None
):往消息队列中存放消息。block可以控制是否阻塞,timeout指定阻塞时候的等待时间。如果不阻塞或者超市,会引起一个full exception。
Queue.
put_nowait
(
item
):相当于
put(item, False)
.
Queue.
get
(
block=True
,
timeout=None
):获取一个消息,其他同put。
以下两个函数用来判断消息对应的任务是否完成。
Queue.
task_done
(
):接受消息的线程通过调用这个函数来说明消息对应的任务已完成。
Queue.
join
(
):调用线程阻塞直到所有消息对应的任务已经完成。
消息队列实例中维护的有待完成任务变量。每接收到一个消息该值自增一次。每调用一次.task_done()可以使该值减1,当待完成任务值为0的时候,join函数才会返回。
2.2、 queue例子:
import threading import Queue import time class worker(threading.Thread): def __init__(self,queue): threading.Thread.__init__(self) self.queue=queue self.thread_stop= False def run(self): while not self.thread_stop: print( "thread%d %s: waiting for tast" %(self.ident,self.name)) try: task=q.get(block= True, timeout= 20) #接收消息 except Queue.Empty: print( "Nothing to do!i will go home!") self.thread_stop= True break print( "task recv:%s ,task No:%d" % (task[ 0],task[ 1])) print( "i am working") time.sleep( 3) print( "work finished!") q.task_done() #完成一个任务 res=q.qsize() #判断消息队列大小 if res> 0: print( "fuck!There are still %d tasks to do" % (res)) def stop(self): self.thread_stop = True if __name__ == "__main__": q=Queue.Queue( 3) worker=worker(q) worker.start() q.put([ "produce one cup!", 1], block= True, timeout= None) #产生任务消息 q.put([ "produce one desk!", 2], block= True, timeout= None) q.put([ "produce one apple!", 3], block= True, timeout= None) q.put([ "produce one banana!", 4], block= True, timeout= None) q.put([ "produce one bag!", 5], block= True, timeout= None) print( "***************leader:wait for finish!") q.join() #等待所有任务完成 print( "***************leader:all task finished!")
以上程序实现一个简单的消费者-生产者模型。主线程通过消息队列向worker线程分配任务,worker线程完成任务后调用
task_done()使得待完成任务数减一。主线程通过join等待生产者完成任务,生产者完成所有任务后主线程退出。代码输出:
thread139958685849344 Thread-1: waiting for tast 1task recv:produce one cup! ,task No:1i am workingwork finished!fuck!There are still 3 tasks to dothread139958685849344 Thread-1: waiting for tast 1task recv:produce one desk! ,task No:2i am workingleader:wait for finish!work finished!fuck!There are still 3 tasks to dothread139958685849344 Thread-1: waiting for tast 1task recv:produce one apple! ,task No:3i am workingwork finished!fuck!There are still 2 tasks to dothread139958685849344 Thread-1: waiting for tast 1task recv:produce one banana! ,task No:4i am workingwork finished!fuck!There are still 1 tasks to dothread139958685849344 Thread-1: waiting for tast 1task recv:produce one bag! ,task No:5i am workingwork finished!thread139958685849344 Thread-1: waiting for tast 1***************leader:all task finished!Nothing to do!i will go home!