Python queue (隊列)

queue (隊列)

主要做用

  1. 解耦,使程序實現鬆耦合(一個模塊修改不會影響其餘模塊)
  2. 提升效率

隊列與列表的關係

隊列中數據只有一份,取出就沒有了,區別於列表,列表數據取出只是複製了一份html

分類

FIFO (先入先出)

queue.Queue(maxsize=0)
示例:多線程

import queue

q = queue.Queue()
q.put(1)
q.put(2)
q.put(3)

print(q.get())
print(q.get())
print(q.get())

輸出結果:
1
2
3線程

LIFO (後入先出)

queue.LifoQueue
示例:code

import queue

q = queue.LifoQueue()
q.put(1)
q.put(2)
q.put(3)

print(q.get())
print(q.get())
print(q.get())

輸出結果:
3
2
1htm

PriorityQueue (數據可設置優先級)

queue.PriorityQueue
同優先級的按照 ASCII 排序
示例:blog

import queue

q = queue.PriorityQueue()
q.put((2, '2'))
q.put((1, '1'))
q.put((3, '3'))
q.put((1, 'a'))

print(q.get())
print(q.get())
print(q.get())
print(q.get())

輸出結果:
(1, '1')
(1, 'a')
(2, '2')
(3, '3')排序

queue 模塊

queue 模塊中有 Queue 類,LifoQueue、PriorityQueue 都繼承了 Queue繼承

maxsize

maxsize 是實例化 Queue 類時的一個參數,默認爲 0
Queue(maxsize=0) 能夠控制隊列中數據的容量隊列

put

Queue.put(block=True, timeout=None)
block 用於設置是否阻塞, timeout 用於設置阻塞時等待時長
put_nowait() = put(block=False)開發

阻塞

當隊列滿了以後,put 就會阻塞,一直等待隊列再也不滿時向裏面添加數據

不阻塞

當隊列滿了以後,若是設置 put 不阻塞,或者等待時長到了以後會報錯:queue.Full

get

Queue.get(block=True, timeout=None)
get_nowait() = get(block=False)

阻塞

當隊列空了以後,get 就會阻塞,一直等待隊列中有數據後再獲取數據

不阻塞

當隊列空了以後,若是設置 get 不阻塞,或者等待時長到了以後會報錯:_queue.Empty

full & empty

Queue.empty()/Queue.full() 用於判斷隊列是否爲空、滿
儘可能使用 qsize 代替

qsize

Queue.qsize() 用於獲取隊列中大體的數據量
注意:在多線程的狀況下不可靠
由於在獲取 qsize 時,其餘線程可能又對隊列進行操做了

join

join 會在隊列存在未完成任務時阻塞,等待隊列無未完成任務,須要配合 task_done 使用

task_done

執行一次 put 會讓未完成任務 +1 ,可是執行 get 並不會讓未完成任務 -1 ,須要使用 task_done 讓未完成任務 -1 ,不然 join 就沒法判斷
隊列爲空時執行會報錯:ValueError: task_done() called too many times
示例:

import queue
import threading
import time


def q_put():
    for i in range(10):
        q.put('1')
    while True:
        q.put('2')
        time.sleep(1)


def q_get():
    while True:
        temp = q.get()
        q.task_done()
        print(temp)
        time.sleep(0.3)


q = queue.Queue()
t1 = threading.Thread(target=q_put)
t2 = threading.Thread(target=q_get)
t1.start()
t2.start()
q.join()
print('queue is empty now')

主線程執行到 q.join 就開始阻塞,當 t2 線程將隊列中的數據所有取出以後,主線程才繼續執行。
若是將 task_done 註釋掉主線程就永遠阻塞在 q.join,再也不繼續向下執行

生產者消費者模型(主要用於解耦)

在多線程開發當中,若是生產線程處理速度很快,而消費線程處理速度很慢,那麼生產線程就必須等待消費線程處理完,才能繼續生產數據。一樣的道理,若是消費線程的處理能力大於生產線程,那麼消費線程就必須等待生產線程。爲了解決這個問題因而引入了生產者和消費者模式
生產者消費者模式是經過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通信,而經過阻塞隊列來進行通信,因此生產者生產完數據以後不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產者要數據,而是直接從阻塞隊列裏取,阻塞隊列就至關於一個緩衝區,平衡了生產者和消費者的處理能力。
示例:

import threading
import time
import queue


def producer():
    count = 1
    while 1:
        q.put('No.%i' % count)
        print('Producer put No.%i' % count)
        time.sleep(1)
        count += 1


def customer(name):
    while 1:
        print('%s get %s' % (name, q.get()))
        time.sleep(1.5)


q = queue.Queue(maxsize=5)
p = threading.Thread(target=producer, )
c = threading.Thread(target=customer, args=('jack', ))
p.start()
c.start()

使用生成器也能夠實現簡單的生產者消費者模型
點擊查看 -> 生成器

相關文章
相關標籤/搜索