1.简介:
- Python 很早就开始使用多种不同的并发编程方法,包括
多线程
、加载子进程
等。
2.单线程引入:
- 先看一段代码:
#coding=utf-8 import time def greet(index): print '人生苦短,我用Python!-%d' % index time.sleep(0.5) def line_run(): for i in range(5): greet(i) if __name__ == "__main__":#入口函数的判断 line_run() #结果:当然是依次顺序的打印这句话了,,, 人生苦短,我用Python!-0 人生苦短,我用Python!-1 人生苦短,我用Python!-2 人生苦短,我用Python!-3 人生苦短,我用Python!-4 Process finished with exit code 0
注意:
-
if __name__ == "__main__":
----------------简要说明如下:- 有句话经典的概括了这段代码的意义:
Make a script both importable and executable
- 意思就是让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行。
- 调试代码的时候,在
if __name__ == '__main__'
中加入一些我们需要调试的代码,可以让外部模块调用的时候不执行调试代码,但是如果我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!
- 有句话经典的概括了这段代码的意义:
3.多线程引入:
- 改进后的代码:
#coding=utf-8 import time import threading def greet(index): print '人生苦短,我用Python!-%d'%index time.sleep(0.5) def async_run(): for i in range(5): th = threading.Thread(target=greet,args=[i])#target指的函数名args为参数 th.start() if __name__ == "__main__": async_run() #结果:同时打印下列的语句:请自己亲测方能看到效果。 人生苦短,我用Python!-0 人生苦短,我用Python!-1 人生苦短,我用Python!-2 人生苦短,我用Python!-3 人生苦短,我用Python!-4
4.threading
库可用来在单独的线程中执行任意的Python可调用对象。
-
t = threading.Thread(target=函数名,args=[参数])
#创建线程t。 -
t.start()
执行线程。 - 当创建一个线程实例时,在调用它的start()方法之前(需要提供目标函数以及相应的参数),线程并不会立即执行。
- 该线程实例完全由操作系统来管理。一旦启用后,线程就开始独立运行,直到目标函数返回为至。
- 可以通过查询线程实例来判断它是否还在运行。
t.is_alive()---查看线程是否运行
。 -
t.join()
请求连接到某个线程上,这个方法会等待线程结束。 - 对于需要长时间运行的线程或者一直不断运行的后台任务,应该考虑将这些线程设置为
daemon(即,守护线程)
:t = threading.Thread(target=函数名,args=[参数],daemon=True)
注意:daemon线程是无法被连接的。但是当主线程结束后则会自动销毁。
5.举例:生产者和消费者
- 代码:两个线程对公共变量MONEY操作
#coding=utf-8 import time import threading import random MONEY = 0#全局变量MONEY gLock = threading.Lock()#锁 #生产者 def procuder(): while True: global MONEY#声明一个全局变量 rand_money = random.randint(10,100)#随机生产一个数值 gLock.acquire()#用acquire()申请锁 MONEY += rand_money gLock.release()#释放锁 print '生产者%s-生产了:%d' % (threading.current_thread, MONEY) time.sleep(0.5)#睡眠 #消费者 def customer(): while True: global MONEY #声明一个全局变量 rand_money = random.randint(10,100)#随机生成一个数值 if MONEY > rand_money: print '消费者%s-消费了:%d' %(threading.current_thread,rand_money) gLock.acquire#加锁 MONEY -= rand_money gLock.release#释放 else: print '需要消费的钱为:%d,余额为:%d' %(rand_money,MONEY)
- 用
threading.Lock()
创建锁,用acquire()
申请锁,每次只有一个线程获得锁,其他线程必须等此线程release()
后才能获得锁。 -
RLock
允许在同一线程中被多次acquire
。而Lock
却不允许这种情况。注意:如果使用
RLock
,那么acquire
和release
必须成对出现,即同一线程中调用了n次acquire
,必须调用n次的release
才能真正释放所占用的琐。
网友评论