(三十四)线程的队列
Posted asia-yang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(三十四)线程的队列相关的知识,希望对你有一定的参考价值。
一、线程的其他方法
1.threading.current_thread()获取对象可以使用的方法
def fn(): pass t = Thread(target=fn,) t.start() obj = threading.current_thread() print(obj.getName(), obj.name) print(obj.ident)
2.threading直接可以使用的方法
print(threading.enumerate())#获取当前活跃的线程的列表 print(threading.active_count())#获取当前活跃的线程的总数
二、线程队列
- 普通队列
import queue q = queue.Queue(5)#不给数量,这个队列就是无限大的 q.put(1) q.put(2) q.put(3) q.put(4) q.put(5) #print(q.full())#判断队列是否已满,不过有时不太准确 #print(q.qsize())#获取队列中元素的的数量,其实这个方法里面里面也是使用的len()函数 try: # q.put(6)#如果队列装满了,会一直停留在这里 q.put_nowait(6)#如果队列满了,会报错,使用try后,可以抓取异常,然后继续向下执行 except Exception: print(‘zhe queue is full‘) #print(q.empty())#查看队列是否已空,不过有时不太准确 print(q.get()) print(q.get()) print(q.get()) print(q.get()) print(q.get()) try: print(q.get()) except Exception: print(‘zhe queue is empty‘)
2.LifoQueue--先进后出队列,获取顺序类似栈
这就是一个继承了Queue的列表,其他的方法就是继承于Queue。
q = queue.LifoQueue(3) q.put(1)#添加数据就是向列表里append()数据 q.put(2) q.put(3) print(q.get())#就是使用pop()删除列表 print(q.get()) print(q.get()) 结果: 3 2 1
第一步初始化一个列表:
def _init(self, maxsize): self.queue = []
第二步添加数据:
def _put(self, item): self.queue.append(item)
第三部删除数据:
def _get(self): return self.queue.pop()
3.PriorityQueue--优先级队列
q = queue.PriorityQueue() q.put((3,‘4‘)) q.put((2,3)) q.put((1,‘d‘)) q.put((5,‘s‘)) q.put((4,‘w‘)) print(q.get()) print(q.get()) print(q.get()) print(q.get()) print(q.get()) 结果: (1, ‘d‘) (2, 3) (3, ‘4‘) (4, ‘w‘) (5, ‘s‘)
结果按照元组中第一个元素的ASCII码的升序排序后输出,如果第一元素相等,就按照第二个元素的ASCII码的升序排列,以此类推。但是,字典元素不可比较。相对应比较的两个元素必须是同类型的。
优先级队列也是一个列表:
def _init(self, maxsize): self.queue = []
就是增加和获取时,与列表有些区别。
三、线程池
- ThreadPoolExecutor
(1) map
def f(n): time.sleep(0.5) print(n) t = ThreadPoolExecutor(4) # 默认数量是,CPU个数的5倍 t.map(f, range(10))
(2)submit()
def f(n): time.sleep(0.3) # print(n) return n**2 Def fn(m): Print(m) t = ThreadPoolExecutor(4) # 默认数量是,CPU个数的5倍 t_lst = [] for i in range(10): #功能后面的参数是无敌传参,*args,**kwargs,传递实参的个数不限制,但是形参的个数与形式也要跟实参的一一对应上 res = t.submit(f, n=i) #t.submit()..add_done_callback(fn)#回调函数 #print(res)#返回的是结果对象 # print(res.result())#这也是一个不拿到结果,誓不罢休的方法 t_lst.append(res) # for th in t_lst:#在shutdown()之前是每四个一次显示出来 # print(th.result()) # 相当于进程池的close()和join()两个方法,其实里面是让每个线程都调用了join(). t.shutdown() for th in t_lst:#会一下子展示出来数据 print(th.result())
2.ProcessPoolExecutor
与ThreadPoolExcutor的使用方法一样大的。
四、协程
协程是线程里最小的执行单元。首先得下载两个模块--greenlet和gevent。
- greenlet
from greenleet import greenlet def f1(): print(‘f1---1111‘) g2.switch() print(‘f1---2222‘) def f2(): print(‘f2---1111‘) g1.switch() g1 = greenlet(f1) g2 = greenlet(f2) g1.switch() 结果: f1---1111 f2---1111 f1---2222 def f1(c): print(‘f1---1111‘,c) g2.switch(‘Tom‘) print(‘f1---2222‘,c) def f2(c): print(‘f2---1111‘,c) g1.switch()#此处也可以添加参数,结果和现在就不一样了,可以试试看 g1 = greenlet(f1) g2 = greenlet(f2) g1.switch(‘TOM‘) 结果: f1---1111 TOM f2---1111 Tom f1---2222 TOM
greenlet利用switch切换,执行不同代码块的功能。
2.gevent
def f1(): print(‘f1---11111‘) gevent.sleep(1) #time.sleep(1) print(‘f1---22222‘) def f2(): print(‘f2---11111‘) gevent.sleep(2) #time.sleep(1) print(‘f2---2222‘) g1 = gevent.spawn(f1) g2 = gevent.spawn(f2) g1.join()#需要有 g2.join() #gevent.joinall([g1,g2])#相当于上面的两个一起
gevent只识别自己的sleep(),time.sleep()不能被识别。为了类似time.sleep()这样的阻塞被识别(还有input(),打开文件,读取数据等),使用下面的方式:
from gevent import monkey; monkey.patch_all()
Python查看API:https://docs.python.org/3.7/library/os.html
以上是关于(三十四)线程的队列的主要内容,如果未能解决你的问题,请参考以下文章
Qt系列文章之三十四 (线程题外话---从pthread 到QThread)