Python 多线程
一、线程的使用
需导入模块: from threading import Thread
二、基本使用
1 def fun1(arg1, v): 2 print(arg1) 3 4 print('before') 5 t1 = Thread(target=fun1, args=('aaa',11,)) 6 t1.start() 7 print('此线程名称:', t1.getName()) 8 9 t2 = Thread(target=fun1, args=('bbb',22,)) 10 t2.start() 11 print('此线程名称:', t2.getName()) 12 13 print('after')
三、常用方法
- start
- getName()
- setName()
- isDaemon()
- setDaemon()
- join(timeout)
- run()
1 def fun2(): 2 for i in range(100): 3 print(i) 4 time.sleep(1) 5 6 print('start') 7 t1 = Thread(target=fun2) 8 print('是否守护线程:', t1.isDaemon()) #默认为False,自动执行 9 #设置为守护线程,不自动执行,主程序执行完则子线程不执行, 10 #主程序如果没执行完,则子线程随着主程序执行,直至主程序结束,子线程也跟着结束 11 t1.setDaemon(True) 12 t1.start() 13 print('after1') 14 print('after2') 15 print('after3') 16 time.sleep(10)
1 def fun1(): 2 for i in range(10): 3 print(i) 4 time.sleep(1) 5 6 print('before') 7 t1 = Thread(target=fun1) 8 t1.start() 9 # t1.join() #主程序执行到join()这里后挺住开始执行子线程,子线程执行结束后主程序继续执行 10 t1.join(5) #最多等5秒,子线程最多执行5秒后主进程继续向下执行,主程序执行结束后,子线程继续执行 11 12 print('after')
四、自定义线程类
1 class MyThread(Thread): 2 def run(self): 3 time.sleep(3) 4 print('我是线程') 5 Thread.run(self) #如果不加此句,则不会执行自定义线程中的函数 6 7 def Bar(): 8 print('bar') 9 10 t1 = MyThread(target=Bar) 11 t1.start() 12 print('over')
五、自定义线程类应用 -- 生产者消费者模型
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 from queue import Queue 5 from threading import Thread 6 import time 7 import random 8 9 class Producer(Thread): 10 def __init__(self, name, queue): 11 ''' 12 生产者初始化 13 :param name:生产者名称 14 :param queue:容器 15 ''' 16 self.__Name = name 17 self.__Queue = queue 18 super(Producer, self).__init__() #调用父类构造方法 19 20 def run(self): 21 while True: 22 if self.__Queue.full(): 23 time.sleep(random.randrange(5)) 24 else: 25 self.__Queue.put('包子') 26 time.sleep(random.randrange(5)) 27 print('%s %s 生产了一个包子' %(self.__Name, time.strftime('%Y-%m-%d %H:%M:%S'))) 28 # Thread.run(self) 29 30 class Customer(Thread): 31 def __init__(self, name, queue): 32 ''' 33 消费者初始化 34 :param name:消费者名称 35 :param queue: 容器 36 ''' 37 self.__Name = name 38 self.__Queue = queue 39 super(Customer, self).__init__() 40 41 def run(self): 42 while True: 43 # print('qsize=',self.__Queue.qsize()) 44 if self.__Queue.empty(): 45 time.sleep(random.randrange(5)) 46 else: 47 self.__Queue.get_nowait() 48 time.sleep(random.randrange(3)) 49 print('%s %s 消费了一个包子,还剩%d个包子' %(self.__Name, time.strftime('%Y-%m-%d %H:%M:%S'), self.__Queue.qsize())) 50 # Thread.run(self) 51 52 que = Queue(maxsize=100) 53 54 # print(que.qsize()) 55 56 liFu = Producer('李师傅', que) 57 liFu.start() 58 59 zhangFu = Producer('张师傅', que) 60 zhangFu.start() 61 62 wangFu = Producer('王师傅', que) 63 wangFu.start() 64 65 for item in range(20): 66 name = '陈涛%d' %(item,) 67 temp = Customer(name, que) 68 temp.start() 69 70 71 # print(que.qsize()) 72 73 74 # print(que.qsize()) 75 # que.put('1') 76 # que.put('2') 77 # print('empty: ', que.empty()) 78 # print(que.qsize()) 79 # que.get() 80 # que.get() 81 # print('empty: ', que.empty())
六、函数编程实现生产者消费者模型
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import time 5 import threading 6 import random 7 import queue 8 9 def Producer(name, que): 10 while True: 11 if que.qsize()<3: 12 que.put('包子') 13 print('%s 生产了一个包子' % name) 14 else: 15 print('还有3个包子') 16 time.sleep(random.randrange(2)) 17 18 def Customer(name, que): 19 while True: 20 try: 21 que.get_nowait() 22 print('%s 消费了一个包子' % name) 23 except Exception: 24 print('没有包子了...') 25 time.sleep(random.randrange(3)) 26 27 que = queue.Queue(100) 28 29 xf1 = threading.Thread(target=Producer,args=('师傅1',que)) 30 xf1.start() 31 xf2 = threading.Thread(target=Producer,args=('师傅2',que)) 32 xf2.start() 33 34 xli = threading.Thread(target=Customer,args=('小李',que)) 35 xli.start() 36 xzh = threading.Thread(target=Customer,args=('小张',que)) 37 xzh.start()
七、线程锁
1 #!/usr/bin/evn python 2 # -*- coding:utf-8 -*- 3 4 import threading 5 import time 6 7 num = 0 8 9 def fun1(n): 10 time.sleep(1) 11 global num 12 lock.acquire() # 需要锁,会独占CPU的操作,此句应放在对数据操作的时候 13 num += 1 14 lock.release() #释放锁,对数据操作完后要把锁释放掉,在没有释放前,不可以再添加需要锁 15 # time.sleep(0.01) 如果还有sleep一会,则表示此时不需CPU处理,则下面的print就不会按顺序输出 16 print(num) #如果释放锁后直接print,则是CPU锁定刚结束,还占用着CPU,则会按顺序输出 17 18 lock = threading.Lock() #线程锁 19 20 for i in range(100): 21 t = threading.Thread(target=fun1, args=('n',)) 22 t.start()
八、递归线程锁 #一般不常用
1 #!/usr/bin/evn python 2 # -*- coding:utf-8 -*- 3 4 import threading 5 import time 6 7 num = 0 8 num2 = 0 9 10 def fun1(n): 11 time.sleep(1) 12 global num 13 global num2 14 lock.acquire() # 需要锁,会独占CPU的操作,此句应放在对数据操作的时候 15 num += 1 16 lock.acquire() #使用递归锁就可以在锁内嵌套锁 17 num2 += 1 18 lock.release() #使用递归锁必须要把请求道的锁这个释放 19 lock.release() 20 print(num, num2) 21 22 lock = threading.RLock() #线程锁 23 24 for i in range(100): 25 t = threading.Thread(target=fun1, args=('n',)) 26 t.start()
九、同时进行多个线程
1 #!/usr/bin/evn python 2 # -*- coding:utf-8 -*- 3 4 import threading 5 import time 6 7 num = 0 8 9 def fun1(n): 10 time.sleep(1) 11 global num 12 samp.acquire() # 需要锁,会独占CPU的操作,此句应放在对数据操作的时候 13 num += 1 14 print(num) 15 samp.release() #释放锁,对数据操作完后要把锁释放掉,在没有释放前,不可以再添加需要锁 16 17 # lock = threading.Lock() #线程锁 18 samp = threading.BoundedSemaphore(5) #设置此锁最多同时可以几个进行进行数据修改 19 20 for i in range(200): 21 t = threading.Thread(target=fun1, args=('n',)) 22 t.start()
十、线程间的信息交互
1 #/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import threading 5 import time 6 7 def producer(): 8 print('收银员等人来买包子') 9 event.wait() #等待消息变化,等待有进程执行set()返回True 10 event.clear() #等到set()变成True了,则恢复set()的状态 11 12 print('收银员:有人来买包子') 13 print('收银员:给他做一个包子') 14 time.sleep(3) 15 16 print('收银员:给你包子') 17 event.set() 18 19 20 def customer(): 21 print('张三来买包子') 22 event.set() 23 24 time.sleep(1) 25 print('张三:等待取包子') 26 27 event.wait() 28 event.clear() 29 print('张三:谢谢') 30 31 event = threading.Event() #线程间可以互通消息的变量 32 33 kf = threading.Thread(target=producer) 34 kf.start() 35 zs = threading.Thread(target=customer) 36 zs.start()