今日内容:
1. 线程的其他方法
2.线程队列(重点)
3.线程池(重点)
4.协程
1.线程的其他方法
语法:
Threading.current_thread() # 当前正在运行的线程对象的一个列表
GetName() # 获取线程名
Ident() 获取线程的ID
Threading.active_count() # 当前正在运行的线程数量
import threading import time from threading import Thread,current_thread def f1(): time.sleep(1) print('子进程的名称',current_thread().getName()) # Thread-1 print(f'{i}号线程任务') if __name__=='__main__': t1=Thread(target=f1,args=(2,)) t1.start() print('主线程名称',current_thread().getName()) # MainThread print('主线程ID',current_thread().ident) # 查看主线程ID print(current_thread()) print(threading.enumerate()) #[<_MainThread(MainThread, started 6708)>,
<Thread(Thread-1, started 7848)>] print(threading.active_count()) #主线程和子线程的和 print('主线程结束')
2.线程队列(重点)
Put的数据是一个元组,元组的第一个参数是优先级数字,数字越小优先级越高,越先被get到被取出来,第二个参数是put进去的值,如果说优先级相同,那么值别忘了应该是相同的数据类型,字典不行
线程队列我们这里介绍3种:
import queue
1).先进先出队列 queue.Queue
import queue q=queue.Queue(3) q.put(1) q.put(2) print(q.qsize())# 查看当前队列的长度 q.put(3) try: q.put_nowait(4) # 和put效果一样,但是如果队列满了继续放它会报错 except exception: print('队列满了,放不进去了') print(q.full()) # 查看当前队列是否是满的 print(q.get())#1 print(q.get())#2 print(q.get())#3 print(q.get_nowait()) #和get效果一样,但是如果队列空了继续拿会报错 print(q.empty())# 查看当前队列是否是空的
2).先进后出队列 queue.LifoQueue
import queue q=queue.LifoQueue(3) q.put(1) q.put(2) print(q.qsize()) q.put(3) q.put_nowait(4) print(q.full()) print(q.get())#3 print(q.get())#2 print(q.get())#1 print(q.empty()) #查看队列是否是空的 print(q.get_nowait())
3).优先级队列 queue.PriorrityQueue
q=queue.priorityQueue(3) q.put((2,'alex')) # 必须是元组 q.put((2,'大力')) #数据类型相同才能比较 q.put((-2,'666')) # 如果值里面的元素是int类型,如果这两个值大小,就先拿比较小的那个;如果这两个值大小相同,
那么比较的是下一个元素的第一个ascii码大小,小的优先被取出来 # 如果元素类型是字符串,那么依次比较每个字母的ascii的大小,小的被优先拿出来 # 字典不能比较 print(q.get()) print(q.get()) print(q.get())
3.线程池
from concurrent_futures import ThreadPoolExecutor,ProcessPoolExecutor
p=ThreadPoolExecutor(3) #默认线程的个数是cpu的个数 *5
p=ProcessPoolExecutor(3) #默认进程的个数是cpu的个数
p.map(f1,可迭代对象) # 异步执行
res=p.submit(f1,无敌传参,传什么都行) #异步提交任务
print(res.result()) #和get方法一样,如果没有结果,会等待,阻塞程序
Shutdown()# close+join ,锁定线程池,等待线程池中的所有已经提交的任务全部执行完毕
import time from threading import current_thread from concurrent.futures import ThreadPoolExecutor ,ProcessPoolExecutor def f1(n): time.sleep(1) print(f'{n}号子线程') print('n') if __name__=='__main__': tp=ThreadPoolExecutor(4)
re_list=[]
# 方法1 tp.map(f1,range(10)) # 异步提交任务,参数同样时任务名称,可迭代对象,不打乱顺序
# 方法2
for i in range(10): res=tp.submit(f1,i,'baobao') # submit是给线程池异步提交任务,打乱顺序 re_list.append(res) for el in re_list: print(el.result())
print('主线程结束') tp.shutdown() #主线程等待所有提交给线程池的任务,全部执行完毕 close + join
4.协程
生成器版协程:(有BUG)
import time def f1(): for i in range(10): time.sleep(1) print('f1执行后的结果',i) yield def f2(): g=f1() for i in range(10): time.sleep(1) print('f2执行后的结果',i) next(g) f1() f2()
greenlet 版协程
import time import greenlet def f1(s): print('第一次f1',s) g2.switch('alex')# 切换到g2这个对象的任务去执行 time.sleep(0.4) print('第二次f1',s) g2.switch('baobao') def f2(s): print('第一次f2',s) g1.switch('wusir') time.sleep(0.6) print('第二次f2',s) g1=greenlet(f1)#实例化对象,并将任务名称作为参数传进去 g2=greenlet(f2) g1.switch('zhu')# 执行g1对象的任务
gevent版真正的协程(真正意义上的协程,异步执行程序)
import gevent from gevent import monkey;monkey.patch_all() import time import threading def f1(): print('第一次f1') gevent.sleep(1) print('第二次执行f1') def f2(): print('第一次执行f2') gevent.sleep(1) print('第二次执行f2') g1=gevent.spawn(f1) g2=gevent.spawn(f2) gevent.joinall([g1,g2]) # 相当于g1.join() g2.join() print('主程序任务结束')