Python学习笔记--多线程编程,thread

简介:

        Python提供了thread模块,threading模块与queue模块进行多线程编程。queue模块用于线程间的通信,前两者可以创建线程,不过由于thread模块偏底层,需要手动去完成很多任务,而且同步机制不如threading模块好用,所以建议选择threading模块。

        threading模块中,选择Thread类来创建线程(三种方法):创建一个Thread的实例,并传入一个函数;创建一个Thread的实例,并传入一个可调用的类对象;从Thread派生出一个子类,创建一个这个子类的实例。(代码来自core Python programming)(Python3.3)

创建一个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 test():
    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:
        threads[i].start()

    for i in nloops:
        threads[i].join() #当前process或者thread遇到join()函数时会暂停(挂起),直到这个join()函数连接的thread结束;join(timeout=None)中的timeout参数如果设置了,则会等到设置的时间长度,直到超时或者thread结束,开始运行接下来的代码

    print('all done at',ctime())

if __name__=='__main__':
    test()

结果:

>>> 
starting at: Thu Aug 15 01:34:20 2013
start loopstart loop  01  atat  Thu Aug 15 01:34:20 2013Thu Aug 15 01:34:20 2013

loop 1 done at: Thu Aug 15 01:34:22 2013
loop 0 done at: Thu Aug 15 01:34:24 2013
all done at Thu Aug 15 01:34:25 2013

创建一个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):
        self.func(*self.args)

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

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

    for i in nloops:
        t=threading.Thread(target=ThreadFunc(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__':
    test()

结果:

>>> 
starting at: Thu Aug 15 01:58:32 2013
start loopstart loop  01  atat  Thu Aug 15 01:58:32 2013Thu Aug 15 01:58:32 2013

loop 1 done at: Thu Aug 15 01:58:34 2013
loop 0 done at: Thu Aug 15 01:58:36 2013
all done at Thu Aug 15 01:58:36 2013

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

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):
        self.func(*self.args)

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

def test():
    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__':
    test()

结果:

>>> 
starting at: Thu Aug 15 02:15:18 2013
start loopstart loop 1  at Thu Aug 15 02:15:18 2013
0 at Thu Aug 15 02:15:18 2013
loop 1 done at: Thu Aug 15 02:15:20 2013
loop 0 done at: Thu Aug 15 02:15:22 2013
all done at Thu Aug 15 02:15:22 2013

单线程、多线程速度对比:

对多线程使用第三者创建线程的方法。计算斐波纳挈、阶乘、累加和的结果:

首先,编写一个单独的模块myThread.py,专门生成线程,然后使用的时候,只需要import myThread 就可以了。

import threading
from time import sleep,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=self.func(*self.args)
        print(self.name,'finished at:',ctime()) #end of module myThread
创建线程并计算:

from myThread import MyThread
from time import ctime,sleep

def fib(x):
    sleep(0.005)
    if x<2:
        return 1
    return (fib(x-2)+fib(x-1))

def fac(x):
    sleep(0.1)
    if x<2:
        return 1
    return (x*fac(x-1))

def sumF(x):
    sleep(0.1)
    if x<2:
        return 1
    return (x+sumF(x-1))

funcs=[fib, fac, sumF]
n=12

def test():
    nfuncs=range(len(funcs))

    print('***SINGLE THREAD')
    for i in nfuncs:
        print('starting',funcs[i].__name__,'at:',ctime())
        print(funcs[i](n))
        print(funcs[i].__name__,'finished at:',ctime())

    print('\n***MULTIPLE THREADS')
    threads=[]
    for i in nfuncs:
        t=MyThread(funcs[i],(n,),funcs[i].__name__)
        threads.append(t)

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

    for i in nfuncs:
        threads[i].join()
        print(threads[i].getResult())

    print('All done.')

if __name__=='__main__':
    test()

结果:

>>> 
***SINGLE THREAD
starting fib at: Thu Aug 15 05:15:10 2013
233
fib finished at: Thu Aug 15 05:15:13 2013
starting fac at: Thu Aug 15 05:15:13 2013
479001600
fac finished at: Thu Aug 15 05:15:14 2013
starting sumF at: Thu Aug 15 05:15:14 2013
78
sumF finished at: Thu Aug 15 05:15:15 2013

***MULTIPLE THREADS
startingstartingstarting   fibfacsumF   at:at:at:   Thu Aug 15 05:15:15 2013Thu Aug 15 05:15:15 2013Thu Aug 15 05:15:15 2013


facsumF  finished at:finished at:  Thu Aug 15 05:15:16 2013Thu Aug 15 05:15:16 2013

fib finished at: Thu Aug 15 05:15:17 2013
233
479001600
78
All done.

queue模块进行线程间通信:

import random
from time import sleep
from queue import Queue
from myThread import MyThread

def writeQ(queue):
    print('producting object for Q...')
    queue.put('xxx',1) #第一个参数为要写入Queue的数据,第二个参数为默认值,表示当Queue满的时候,会使线程暂停,直到空出一个位置
    print('size now',queue.qsize())

def readQ(queue):
    val=queue.get(1) #这个参数为默认参数,表示当Queue为空时,线程暂停,直到有了一个数据
    print('consumed object from Q... size now',queue.qsize())

def writer(queue,loops):
    for i in range(loops):
        writeQ(queue)
        sleep(random.randint(1,3))

def reader(queue,loops):
    for i in range(loops):
        readQ(queue)
        sleep(random.randint(2,5))

funcs=[writer,reader]
nfuncs=range(len(funcs))

def test():
    nloops=random.randint(2,5) #表示读与写的次数,读写次数相同
    q=Queue(32)

    threads=[]
    for i in nfuncs:
        t=MyThread(funcs[i],(q,nloops),funcs[i].__name__)
        threads.append(t)

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

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

    print('All done.')

if __name__=='__main__':
    test()
    

结果:

>>> 
startingstarting  writerreader  at:at:  Thu Aug 15 05:57:00 2013Thu Aug 15 05:57:00 2013

producting object for Q...
size nowconsumed object from Q... size now  10 #这里不是10,而是一个1,一个0.1上writeQ()输出的,0是readQ()输出的

producting object for Q...
size nowconsumed object from Q... size now  10

producting object for Q...
size now 1
writer finished at: Thu Aug 15 05:57:06 2013
consumed object from Q... size now 0
reader finished at: Thu Aug 15 05:57:10 2013
All done.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值