python多线程

python提供了几个用于多线程编程的模块,包括thread,threading和Queue,前两个模块允许程序员创建和管理线程。thread模块提供了基本的线程和锁的支持,而threading提供了更高级,功能更强的线程管理功能。Queue模块允许用户创建一个可以用于多个线程之间共享数据的队列的数据结构。


thread模块


thread模块提供了基本了生产线程的函数也提供了基本的同步数据结构的锁对象(look object)



先来看一个单线程的程序(假设loop0()和loop1()里做的不是睡眠而是各自独立的,不想关的运算):


</pre><pre name="code" class="python">from time import sleep, ctime

def loop0():
    print 'start loop 0 at:', ctime()
    sleep(4)
    print 'loop 0 done at:', ctime()

def loop1():
    print 'start loop 1 at:', ctime()
    sleep(2)
    print 'loop 1 done at:', ctime()

def main():
    print 'starting at:', ctime()
    loop0()
    loop1()
    print 'all DONE at:', ctime()

if __name__ == '__main__':
    main()


当我们使用Thread提供的多线程机制时,两个线程能够并发的执行


import thread
from time import sleep, ctime

def loop0():
    print 'start loop 0 at:', ctime()
    sleep(4)
    print 'loop 0 done at:', ctime()

def loop1():
    print 'start loop 1 at:', ctime()
    sleep(2)
    print 'loop 1 done at:', ctime()

def main():
    print 'starting at:', ctime()
    thread.start_new_thread(loop0, ())
    thread.start_new_thread(loop1, ())
    sleep(6)
    print 'all DONE at:', ctime()

if __name__ == '__main__':
    main()


其运行结果如下


starting at: Thu Jul  2 16:16:57 2015
start loop 0 at: Thu Jul  2 16:16:57 2015
 start loop 1 at: Thu Jul  2 16:16:57 2015
loop 1 done at: Thu Jul  2 16:16:59 2015
loop 0 done at: Thu Jul  2 16:17:01 2015
all DONE at: Thu Jul  2 16:17:03 2015

其中sleep(6)是为了让主线程停下来,不然loop1(),loop0()还没有开始运行主程序就已经运行到“all done”。

在这里我们使用的是sleep()勉强实现了同步但是程序的总体运行时间并没有减少,更改程序,我们也可以使用锁来实现:


import thread
from time import sleep, ctime

loops = [4, 2]

def loop(nloop, nsec, lock):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()
    lock.release() #每个loop事先被分配了一个锁,在睡眠时间完成后,释放相应的锁以通知主线程

def main():
    print 'starting threads...'
    locks = []
    nloops = range(len(loops))

    for i in nloops:
        lock = thread.allocate_lock()#创建锁列表
        lock.acquire()#获取锁,表示把锁关上
        locks.append(lock)#放入锁列表

    for i in nloops:#创建线程
        thread.start_new_thread(loop, 
            (i, loops[i], locks[i]))

    for i in nloops:#暂停主线程,直到两个锁都被解锁
        while locks[i].locked(): pass

    print 'all DONE at:', ctime()

if __name__ == '__main__':#只有在直接运行这个脚本时才运行主函数
    main()

运行结果如下


start loop 1 start loop 0 at:at: Thu Jul  2 16:39:34 2015
 Thu Jul  2 16:39:34 2015
loop 1 done at: Thu Jul  2 16:39:36 2015
loop 0 done at: Thu Jul  2 16:39:38 2015
all DONE at: Thu Jul  2 16:39:38 2015


threading模块


threading模块支持守护线程,守护线程一般是一个等待客户请求服务的服务器,如果没有客户提出请求,它就在那儿等着,如果你设定一个线程为守护线程,就表示你在说这个线程是不重要的,在进程退出的时候不用等待这个线程退出,此时可以设定这些线程的daemon属性(在线程开始之前setDaemon()函数为True),如果你要等待子线程完成再退出,那就什么也不做,或者显式的调用setDaemon(False)以保证其daemon

Thread类

用Thread类你有多种方法来创建线程:

1.创建一个Thread实例,传给它一个函数;

2.创建一个Thread实例,传给它一个可调用的类对象;

3.从Thread派生出一个子类,创建一个这个子类的实例;


Thread的函数



创建一个Thread实例,传给它一个函数

import threading
from time import sleep, ctime

loops = [ 4, 2 ]

def loop(nloop, nsec):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()

def main():
    print 'starting at:', ctime()
    threads = []
    nloops = range(len(loops))

    for i in nloops:
        t = threading.Thread(target=loop,
	    args=(i, loops[i]))
        threads.append(t)

    for i in nloops:            # start threads
        threads[i].start()

    for i in nloops:            # wait for all
        threads[i].join()       # threads to finish

    print 'all DONE at:', ctime()

if __name__ == '__main__':
    main()

创建线程的时候新的线程不会马上开始,只有等到调用start()才会开始执行,join()函数会等待直到线程结束,或者当给了timeout()参数的时候,会等到超时为止。


创建一个Thread实例,传给它一个可调用的类对象


可以传一个可调用的类的实例供线程启动的时候执行。


import threading
from time import sleep, ctime

loops = [ 4, 2 ]

class ThreadFunc(object):

    def __init__(self, func, args, name=''):
        self.name = name
        self.func = func
        self.args = args

    def __call__(self):
        apply(self.func, self.args)

def loop(nloop, nsec):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()

def main():
    print 'starting at:', ctime()
    threads = []
    nloops = range(len(loops))

    for i in nloops:	# create all threads
        t = threading.Thread(
	    target=ThreadFunc(loop, (i, loops[i]),
	    loop.__name__))
        threads.append(t)

    for i in nloops:	# start all threads
        threads[i].start()

    for i in nloops:	# wait for completion
        threads[i].join()

    print 'all DONE at:', ctime()

if __name__ == '__main__':
    main()


从Thread派生出一个子类,创建一个这个子类的实例


与上一个程序不同的是(1)MyThread子类构造器一定要先调用基类构造器;(2)_call_()在子类中名字要改为run()

import threading
from time import sleep, ctime

loops = [ 4, 2 ]

class MyThread(threading.Thread):
    def __init__(self, func, args, name=''):
        threading.Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args

    def run(self):
        apply(self.func, self.args)

def loop(nloop, nsec):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()

def main():
    print 'starting at:', ctime()
    threads = []
    nloops = range(len(loops))

    for i in nloops:
        t = MyThread(loop, (i, loops[i]),
	    loop.__name__)
        threads.append(t)

    for i in nloops:
        threads[i].start()

    for i in nloops:
        threads[i].join()

    print 'all DONE at:', ctime()

if __name__ == '__main__':
    main()

可以把myThread单独写成一个模块,以便以后更加通用:


import threading
from time import time, ctime

class MyThread(threading.Thread):
    def __init__(self, func, args, name=''):
        threading.Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args

    def getResult(self):
        return self.res

    def run(self):
        print 'starting', self.name, 'at:', \
	    ctime()
        self.res = apply(self.func, self.args)
        print self.name, 'finished at:', \
	    ctime()


除了同步对象和线程外,thread模块还提供了一些函数:






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值