以前咱们已经学会如何在代码块中建立新的线程去执行咱们要同步执行的多个任务,可是线程的世界远不止如此。接下来,咱们要介绍的是整个threading模块。threading基于Java的线程模型设计。锁(Lock)和条件变量(Condition)在Java中是对象的基本行为(每个对象都自带了锁和条件变量),而在Python中则是独立的对象,因此python的threading模块中还提供了Lock,Rlock,Condition,Event等经常使用类,它们在python中是独立于Tread模块的,可是却与线程紧密相关,不可分割。html
须要注意的是:python的线程中没有优先级、线程组,也不能被中止、暂停、恢复、中断,线程只能随着线程中的代码执行完毕而被销毁。查了n多资料以后终于接受了以上事实,我的以为这是python的一个坑,致使了我在实现线程池的时候没法中止已经注入了方法且执行超时的线程。python
threading模块提供的类:
Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local.多线程
threading 模块提供的经常使用方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。app
threading模块经常使用类详解ide
Thread类:咱们使用Thread类来建立新的线程学习
1 import time 2 import threading 3 4 def printNum(a): 5 print 'num:',a 6 time.sleep(1) 7 8 def ThreadTest(i): 9 return threading.Thread(target=printNum, args=(999,)) 10 11 thread_arr = [] 12 for i in range(10): 13 t = ThreadTest(i) 14 thread_arr.append(t) 15 16 for t in thread_arr: 17 t.start() 18 19 for t in thread_arr: 20 t.join() 21 22 print 'finished'
Lock类和Rlock类:因为线程之间随机调度:某线程可能在执行n条后,CPU接着执行其余线程。为了多个线程同时操做一个内存中的资源时不产生混乱,咱们使用锁ui
不管是lock仍是rlock,提供的方法都很是简单,acquire和release。可是rlock和lock的区别是什么呢?RLock容许在同一线程中被屡次acquire。而Lock却不容许这种状况。注意:若是使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的锁。spa
1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 __author__ = 'Eva_J' 4 5 import threading 6 lock = threading.Lock() #Lock对象 7 lock.acquire() 8 lock.acquire() #产生了死锁。 9 lock.release() 10 lock.release() 11 12 13 import threading 14 rLock = threading.RLock() #RLock对象 15 rLock.acquire() 16 rLock.acquire() #在同一线程内,程序不会堵塞。 17 rLock.release() 18 rLock.release()
Condition类:条件变量对象能让一个线程停下来,等待其它线程知足了某个“条件”。如,状态的改变或值的改变。线程
比较经典的例子是下面这个生产者与消费者的例子,这个例子网上一搜处处都是,这里简单解释一下这段代码的意义,代码中写了两个类,Consumer和Producer,分别继承了Thread类,咱们分别初始化这两个类得到了c和p对象,并启动这两个线程。则这两个线程去执行run方法(这里与Thread类内部的调度有关),定义了producer全局变量和condition对象为全局变量,当producer不大于1时,消费者线程被condition对象阻塞,不能继续消费(这里是再也不递减),当producer不小于10时,生产者线程被condition对象阻塞,再也不生产(这里是再也不累加),代码在下面,拿去执行,断点一下就明白了。设计
1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 __author__ = 'Eva_J' 4 5 import threading 6 import time 7 8 condition = threading.Condition() 9 products = 0 10 11 class Producer(threading.Thread): 12 def __init__(self): 13 threading.Thread.__init__(self) 14 15 def run(self): 16 global condition, products 17 while True: 18 if condition.acquire(): 19 if products < 10: 20 products += 1; 21 print "Producer(%s):deliver one, now products:%s" %(self.name, products) 22 condition.notify() 23 else: 24 print "Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products) 25 condition.wait(); 26 condition.release() 27 time.sleep(2) 28 29 class Consumer(threading.Thread): 30 def __init__(self): 31 threading.Thread.__init__(self) 32 33 def run(self): 34 global condition, products 35 while True: 36 if condition.acquire(): 37 if products > 1: 38 products -= 1 39 print "Consumer(%s):consume one, now products:%s" %(self.name, products) 40 condition.notify() 41 else: 42 print "Consumer(%s):only 1, stop consume, products:%s" %(self.name, products) 43 condition.wait(); 44 condition.release() 45 time.sleep(2) 46 47 if __name__ == "__main__": 48 for p in range(0, 2): 49 p = Producer() 50 p.start() 51 52 for c in range(0, 10): 53 c = Consumer() 54 c.start()
Event类:通用的条件变量。多个线程能够等待某个事件的发生,在事件发生后,全部的线程都会被激活。
这是一个比较关键的类,我在写线程池的时候看到python的threadpool模块也用到了。它的意义在于能够控制属于同一个线程类的多个实例化对象,让他们同时阻塞或者执行。配合队列来实现一个线程池很是好用。在接下里的博客中咱们还要继续介绍。先放一个小例子在这里练练手,了解一下event的用法。
1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 __author__ = 'Eva_J' 4 5 import threading 6 import time 7 8 event = threading.Event() 9 10 def func(): 11 # 等待事件,进入等待阻塞状态 12 print '%s wait for event...' % threading.currentThread().getName() 13 event.wait() 14 15 # 收到事件后进入运行状态 16 print '%s recv event.' % threading.currentThread().getName() 17 18 t1 = threading.Thread(target=func) 19 t2 = threading.Thread(target=func) 20 t1.start() 21 t2.start() 22 23 time.sleep(2) 24 25 # 发送事件通知 26 print 'MainThread set event.' 27 event.set()
参考文献:
python多线程学习小结:http://www.myexception.cn/perl-python/1688021.html
python线程指南:http://www.cnblogs.com/huxi/archive/2010/06/26/1765808.html
threading.RLock和threading.Lock:http://blog.sina.com.cn/s/blog_5dd2af0901012rad.html
python的进程、线程与协程:http://www.cnblogs.com/wupeiqi/articles/5040827.html