您的位置:首页 > 编程语言 > Python开发

<PY><core python programming笔记>C18 多线程编程

2014-05-26 13:58 666 查看

C18 多线程编程

18.1 动机

可能中间过程需要子任务,本质上是异步的,需要有多个并发事务(事实上单CPU只能串行,通过分时处理看起来并行),

各个事务的运行顺序是不确定的,随机的,不可预测的。

顺序执行的程序必须使用非阻塞的I/O,或者可以是带有计数器的阻塞I/O

多线程编程是可能使用同一数据,这样就需要由单一的功能来组织这个数据操作,防止冲突

UserRequestThread 负责读取客户的输入,可能是一个I/O信道。请求放入线程队列中。

RequestProcessor 负责从队列中获取并处理请求,由下面的线程提供输出

ReplyThread 负责给用户取出输出

18.2线程和进程

线程的组织范围比进程小

进程是可以去分配资源的,线程在进程中共享数据资源

18.3Python、线程和全局解释器锁

18.3.1 GIL--全局解释器锁

控制线程的运行

编写扩展时可以主动解锁GIL

18.3.2 退出线程

thread.exit()

sys.exit()

18.3.4 没有线程的情况

比如时间的控制sleep(second)就不好控制

18.3.5 threading

Python提供thread、threading、Quene模块(不推荐使用thread模块,因为功能很有限且与threading冲突,

且不支持守护线程)

18.4 thread模块

模块函数

start_new_thread(function,args kwargs=None) 指定参数,新建线程

allocate_lock() 分配一个LockType类型的锁对象

exit() 让线程退出

LockType类型锁对象方法

acquire(wait=None) 尝试获取锁对象

locked() 如果获取了锁对象返回True,否则返回False

release() 释放锁

#thread1.py
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()

#thread2.py
#coding=UTF-8
#锁比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()
    print 'released'
def main():
    print 'starting at:',ctime()
    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()


18.5 threading 模块

模块对象

Thread 表示一个线程的执行的对象

Lock 锁原语对象(更thread模块里的锁对象相同)

RLock 可重入锁对象。使单线程可以再次获得已经获得了的锁(递归锁定)

Condition 条件变量对象能让一个线程停下来,等待其他线程满足了某个条件。

Event 通用的条件变量。在某个事件发生后多个线程都被激活

Semaphore 为等待锁的线程提供一个类似“等候室”的结构

BoundedSemaphore 和上面类似,但不允许超过初始值

Timer 与Thread相似,只是它要等待一段时间后才开始运行

函数

start() 开始线程的执行

run() 定义线程的功能的函数,一般会被子类重写

join(timeout=None) 程序挂起,直到线程结束,设置timeout是最大阻塞时间

getName() 获得线程名称

isAlive() 线程是否运行中

isDaemon() 返回线程的daemon标志

setDaemon(daemonic) 设置daemon为daemonic

18.5.1 使用threading模块

#coding=UTF-8
import threading
from time import sleep,ctime

loops=[4,2,3,6]

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:
        threads[i].start()#用start启动
    for i in nloops:      #等待所有
        threads[i].join() #允许主线程等待线程的结束
    print 'all done at:',ctime()

if __name__=='__main__':
    main()

#使用类
#coding=UTF-8
import threading
from time import sleep,ctime

loops=[3,5,7,2,4,8]

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:
        threads[i].join()
    print 'alll done at:',ctime()

if __name__=='__main__':
    main()


18.5.3 threading模块中的其他函数

activeCount() 当前活动的线程对象的数量

currentThread() 返回当前线程对象

enumerate() 返回当前活动线程的列表

settrace() 为所有线程设置一跟踪函数

setprofile() 为所有线程设置一个profile函数

18.5.4 生产者--消费者问题和Quene模块

queue(size) 创建一个大小为size的Queue对象

qsize() 返回队列大小

empty() 队列为空则返回True,否则返回False

full() 队列为满则返回True,否则返回False

put(item,block=0) 把item放到队列中,如果给出了block,函数会一直阻塞到队列中有空间为止

get(block=0) 从队列中取一个对象,如果给力block,函数会一直阻塞到队列中有对象为止

18.6相关模块

thread

threading

Quene

mutex

SocketSever
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: