(三十四)線程的隊列
阿新 • • 發佈:2019-02-08
取數 elf https tom thread ocs cpu mon sta
一、線程的其他方法
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
(三十四)線程的隊列