其他分享
首页 > 其他分享> > (三十四)线程的队列

(三十四)线程的队列

作者:互联网

一、线程的其他方法

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())#获取当前活跃的线程的总数

 

  

二、线程队列

  1. 普通队列
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 = []

  

就是增加和获取时,与列表有些区别。

三、线程池

  1. 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。

 

  1. 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

  

 

标签:f1,f2,get,队列,put,线程,三十四,print,def
来源: https://www.cnblogs.com/asia-yang/p/10356214.html