[ Python - 12 ] 线程的信号量、标志位及队列
线程的信号量
线程的信号量是同时允许一定数量的线程更改数据,主要作用在于限制线程的并发。
#!_*_coding:utf-8_*_ # Author: hkey import threading, time # 线程的信号量 sem = threading.BoundedSemaphore(5) # 实例化信号量并限制并发为5个线程 def run(): sem.acquire() # 开始 print('running...', threading.get_ident()) time.sleep(1) sem.release() # 结束 if __name__ == '__main__': for i in range(20): t = threading.Thread(target=run) t.start()
线程的标志位Events
python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法wait、clear、set
- 事件处理的机制:全局定义一个Flag. 使用threading.Event 实现线程间通信 event = threading.Event() 初始值为False
- 如果'Flag'值为False,那么当程序执行event.wait方法时就会阻塞
- 如果'Flag'值为True,那么event.wait方法便不在阻塞
-
- clear: 将'Flag'设置为False
- set:将'Flag'设置为True
一旦该线程通过wait()方法进入等待状态,直到另一个线程调用Event的set()方法将内置标志设置为True时,该Event会通知所有等待状态的线程恢复运行。
#!_*_coding:utf-8_*_ # Author: hkey import threading, time # 线程的标志位 # 红绿灯, 灯控制车辆 event = threading.Event() def light(): n = 0 while True: if n <= 5: event.set() # 设置为set, wait就不阻塞 绿灯状态 print('\33[42;1m green light \33[0m') elif 5 < n < 10: event.clear() # 将'Flag'设置为False 红灯状态 print('\33[41;1m red light \33[0m') else: n = 0 time.sleep(1) n += 1 def car(): while True: if event.is_set(): print('cars running...') else: print('cars stopped...') event.wait() # 当使用clear方法将Flag为False,使用wait方法阻塞;当使用set方法将Flag设置为True,则恢复运行 time.sleep(1) t1 = threading.Thread(target=light) t2 = threading.Thread(target=car) t1.start() t2.start()
线程的队列
线程的队列共有三种:
class queue.Queue(maxsize=0) #先入先出 class queue.LifoQueue(maxsize=0) # 先入后出 class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列
这里主要使用先入先出模式
生产者消费者模型
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
#!_*_coding:utf-8_*_ # Author: hkey import threading, queue, time q = queue.Queue() def product(): for i in range(10): q.put('包子-%s' %i) # 循环put 10个包子 print('等待取包子') q.join() # 阻塞等待队列被清空 print('所有包子都被取走了。') def consumer(): while not q.empty(): # empty()方法判断队列是否为空,空为True print('吃掉%s' %q.get()) q.task_done() # 告知这个任务执行完了 time.sleep(1) t1 = threading.Thread(target=product) t2 = threading.Thread(target=consumer) t1.start() t2.start()