多线程(thread+queue 售票)
一、理解
如果线程里每从队列里取一次,但没有执行task_done(),则join无法判断队列到底有没有结束,在最后执行个join()是等不到结果的,会一直挂起。
可以理解为,每task_done一次 就从队列里删掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import time 5 from threading import Thread 6 from queue import Queue 7 8 tickets = 100 9 # 队列中,可以放任意类型的数据,线程安全 10 tickets_queue = Queue(100) 11 # 声明退出条件 12 exitFlag = False 13 14 15 class TicketsThread(Thread): 16 17 def __init__(self, thread_id, sell_tickets_queue): 18 super().__init__() 19 self.thread_id = thread_id 20 self.sell_tickets_queue = sell_tickets_queue 21 22 # 代码在run中执行,run中完善功能 23 def run(self): 24 super().run() 25 global tickets 26 global exitFlag 27 while True: 28 # 线程退出的条件 29 if exitFlag: 30 break 31 32 # 获取队列中数据 33 # Queue特点,取出来,没了 34 try: 35 tickets = self.sell_tickets_queue.get(block=False) 36 print('线程:--------%d--------已卖票:%d' % (self.thread_id, tickets)) 37 time.sleep(1) 38 # 通知队列,任务结束 39 self.sell_tickets_queue.task_done() 40 except Exception as e: 41 pass 42 43 44 if __name__ == '__main__': 45 ''' 46 多个线程,执行同一个任务 47 100url,一个线程,可以 48 10个线程,执行现在请求,优化 49 卖票,多线程 50 10个窗口帮助我们卖票 51 ''' 52 for i in range(1, 101): 53 # 向队列中放入100张票 54 tickets_queue.put(i) 55 56 # 创建10个线程,让10个线程一起执行买票 57 for i in range(1, 11): 58 # 创建卖票线程,并且启动 59 my_thread = TicketsThread(i, tickets_queue) 60 # 启动,线程中的run方法,就开始执行 61 my_thread.start() 62 63 # join():判断队列是否为空,如果为空,程序继续向下执行,如果不为空,继续等待。(可以理解为队列锁) 64 tickets_queue.join() 65 exitFlag = True
愿你多向优秀的人学习;
愿你不怕麻烦,勤做总结;
愿你每天都有意义;
愿你不负年华;
愿你……
愿你……
愿你……
愿你一生都快乐!