二十三、Python隊列實現多執行緒(下篇)
@Author: Runsen
在Python中,主要採用隊列和執行緒的方法來實現多執行緒。
@[TOC]
隊列
隊列(queue),是先進先出(FIFO, First-In-First-Out)的線性表,在具體應用中通常用鏈表或者數組來實現,隊列只允許在後端(稱為rear)進行插入操作,在前端(稱為front)進行刪除操作,隊列的操作方式和堆棧類似,唯一的區別在於隊列只允許新數據在後端進行添加。

在Python中隊列可以通過內置模組queue導入,具體導入方法:from queue import Queue。
queue
queue模組提供了適合多執行緒編程的先進先出的數據結構,可以用來在生產者和消費者執行緒之間安全的傳遞消息或者數據;鎖是調用方處理,因此多執行緒可以安全、方便的使用同一隊列實現。

常用屬性和方法:
| 介面 | 描述 |
|---|---|
| put(x) | 入隊 |
| get() | 出隊 |
| empty() | 判斷隊列是否為空 |
| full() | 判斷隊列是否未滿 |
| qsize() | 隊列的當前長度 |
| task_done() | 任務結束 | join() | 等待完成 |
Queue類實現了一個基本的先進先出容器。使用put方法將元素增加到序列的一端,使用get方法從另一端刪除,具體程式碼如下。
import queue
q = queue.Queue()
#添加元素
for i in range(5):
q.put(i)
#刪除元素
while not q.empty():
print(q.get())
運行上面的程式,你將會看到下面的輸出:
0
1
2
3
4
生產者/消費者模式
我們經常會遇到這樣的一個問題,這裡有成千上萬條數據,每次需要取出其中的一條數據進行處理,那麼引入多執行緒該怎麼進行任務分配?
我們可以將數據進行分割然後交給多個執行緒去跑,因為執行緒間數據的共享的問題。
它包含兩類進程:一種只是用來生產數據,例外一種只是用來消費數據.為了串聯他們,通常會採用共享的數據區域,就像一個倉庫.生產者產生的數據都放入倉庫中並不需要關注消費者的行為,消費者只需要從共享倉庫中獲取數據,並不需要關心生產者的行為.
# -*- coding:utf-8 -*-
# time :2019/4/23 10:13
# Author: Maoli
import threading
import time
import random
MONEY = 0
gLock = threading.Lock()
def Procuder():
while True:
global MONEY
random_money = random.randint(10,100)
gLock.acquire() #加鎖
MONEY += random_money
gLock.release() #釋放鎖
print ('生產者%s-生產了%d' % (threading.current_thread,random_money))
time.sleep(0.5)
def Customer():
while True:
global MONEY
random_money = random.randint(10,100)
if MONEY > random_money:
print ('消費者%s-消費了:%d' % (threading.current_thread,random_money))
gLock.acquire()
MONEY -= random_money
gLock.release()
else:
print ('需要消費的錢為:%d,餘額為:%d,' % (random_money,MONEY))
time.sleep(0.5)
def p_c_test():
# 執行3個執行緒,來當作生產者
for x in range(3):
th = threading.Thread(target=Procuder)
th.start()
# 執行3個執行緒,來當作消費者
for x in range(3):
th = threading.Thread(target=Customer)
th.start()
if __name__ == "__main__":
p_c_test()
運行截圖如下:

隊列實現多執行緒
在這裡我們可以使用隊列與執行緒相結合的方式進行任務分配。在生產消費者模式當中用到的是阻塞型queue。在Python當中,我們最常用的queue就是一個支援多執行緒場景的阻塞隊列
隊列執行緒的思想: 首先創建一個全局共享的隊列,隊列中只存在有限個元素,並將所有的數據逐條加入到隊列中,並調用隊列的join函數進行等待。之後便可以開啟若干執行緒,執行緒的任務就是不斷的從隊列中取數據進行處理就可以了。
# -*- coding:utf-8 -*-
# time :2019/4/23 10:35
# Author: Maoli
import threading
import time
import queue
# 下面來通過多執行緒來處理Queue裡面的任務:
def work(q):
while True:
if q.empty():
return
else:
t = q.get()
print("當前執行緒sleep {} 秒".format(t))
time.sleep(t)
def main():
q = queue.Queue()
for i in range(5):
q.put(i) # 往隊列里生成消息
thread_num = 5
threads = []
for i in range(thread_num):
t = threading.Thread(target=work, args=(q,))
# args需要輸出的是一個元組,如果只有一個參數,後面加,表示元組,否則會報錯
threads.append(t)
# 創建5個執行緒
for i in range(thread_num):
threads[i].start()
for i in range(thread_num):
threads[i].join()
if __name__ == "__main__":
start = time.time()
main()
print('耗時:', time.time() - start)
運行上面的程式,你將會看到下面的輸出:
當前執行緒sleep 0 秒
當前執行緒sleep 1 秒
當前執行緒sleep 2 秒
當前執行緒sleep 3 秒
當前執行緒sleep 4 秒
耗時: 4.002955436706543
今天也學到了很多東西呢,明天有什麼新知識呢?真期待鴨如果喜歡文章可以關注我哦
本文已收錄 GitHub,傳送門~ ,裡面更有大廠面試完整考點,歡迎 Star。