1. 程式人生 > >孤荷凌寒自學python第四十三天python 的執行緒同步之Queue物件

孤荷凌寒自學python第四十三天python 的執行緒同步之Queue物件

 孤荷凌寒自學python第四十三天python的執行緒同步之Queue物件

 

(完整學習過程螢幕記錄視訊地址在文末,手寫筆記在文末)

Queue物件是直接操作佇列池的物件,佇列中可以存放多種物件,當然也就可以存放執行緒物件,將多個執行緒物件存放於佇列池中之後,就能非常顯式的操作各個執行緒,非常方便。這是今天學習Queue的皮毛之後的感受,第一次感覺對執行緒有了非常完全的掌控,不像最初學習Lock與RLock那樣,那時感覺完全沒有掌控住執行緒。

一、  引用queue模組

Queue來自於模組queue

注意queue模組的首字母是小寫的;而類名稱Queue的名稱首字母是大寫的。

因此使用前必須 宣告引用queue模組:

import queue

 

二、  得到queue模組中的三個相關佇列類的物件實體(測試程式碼統一在後測試)

在queue模組中其實有三個與佇列相關的類

1

Queue

新的Queue物件=queue. Queue([maxsize])

Queue是指一個 先進先出 的佇列,即先進入佇列 的物件,取出時也先被取出來。

縮寫為:Fifo (First  in  first  out)

 

2

LifoQueue

新的LifoQueue物件=queue. LifoQueue([maxsize])

LifoQueue是指一個 後進先出 的佇列,即後進入佇列 的物件,取出時卻會被先取出來。

縮寫為:Lifo (Last  in  first  out)

 

3

PriorityQueue

新的PriorityQueue物件=queue. PriorityQueue ([maxsize])

PriorityQueue是指一個 優先順序 佇列,即不管進入佇列 的順序如何,取出時都按物件標註的 優先順序來安排 取出順序,優先順序數字小的物件會被優先取出來 。

由於初學乍到,沒有深入學習PriorityQueue,發現它的用法較前兩個物件是不同的。

 

【maxsize】可選形參如果指定 了大於0的實際引數,那麼就表示指定了這個佇列物件的 最大容量(就是說可以容下多少個物件)。如果沒有指定這個形參的實參或指定的實參小於1,那麼都表示這個佇列的容量是無限大的。

 

三、  Queue物件的主要方法(測試程式碼統一在後測試)

1

Queue物件 . put(物件[,block=True[,timeout=0]])

此方法用於將一個物件放入佇列中,其中可選形參block=True,說明預設值是True,此時表示放入佇列是阻塞式的,阻塞執行緒的時間由timeout決定。

關於阻塞式放入,我目前的理解是,如果 佇列 的最大容量已經滿了,但也要等待佇列中有空位時才將物件放入。這種情況下不會報錯,因為在阻塞下等待佇列中有空位發生,就馬上放進去。不過如果指定有timeout時間,則時間用完就不再阻塞以等待了。

如果 block=False,那麼一旦佇列中沒有空位以將物件放入佇列中,那麼,就直接報錯。

 

2

Queue物件 . get([,block=True[,timeout=0]])

此方法將取出佇列中當前按優先順序應當被取出來 的下一個物件,將返回一個物件。

其中可選形參block=True,說明預設值是True,此時表示取出佇列中的元素是阻塞式的,阻塞執行緒的時間由timeout決定。

關於阻塞式取出,我目前的理解是,如果 佇列 中已經沒有物件了(佇列為空),但也要等待佇列中有物件時才繼續取出。這種情況下不會報錯,因為在阻塞下等待佇列中有物件發生,就馬上取出來。不過如果 指定有timeout時間,則時間用完就不再阻塞以等待了。

如果 block=False,那麼一旦佇列中已經沒有物件供取出,那麼,就直接報錯。

 

3

Queue物件 . qsize()

得到佇列中當前的物件個數。

 

4

Queue物件 . maxsize()

得到佇列中當前定義時設定的最大容量個數。

 

5

Queue物件 . empty()

此方法將返回佇列是否已經為空,將返回一個布林物件。

 

6

Queue物件 . not_empty()

此方法將返回佇列是否不是空的,將返回一個布林物件。

 

7

Queue物件 . full()

此方法將返回佇列是否已經裝滿,將返回一個布林物件。

 

8

Queue物件 . join()

執行此方法將等待佇列中所有元素都被取出,佇列為空時才執行後續操作。

 

 

 

四、  將檔案由兩個執行緒反覆同步寫和讀的實現由Queue佇列來實現

程式碼如下:

importthreading

import queue

fromdatetime import datetime

from time import sleep

 

strf='1.txt'

 

def read(n):

           

            with open(strf,'r',encoding='utf-8') as f:

                lstA=f.readlines()

           

            print('讀取第' + str(n) + '次' + str(lstA)  + '\n')

 

       

def write(n):

 

        with open(strf,'w',encoding='utf-8') as f:

            lstA=['寫入','第' + str(n) + '次']

            f.writelines(lstA)

        #sleep(1)

        print(str(lstA) +'\n') 

 

       

 

   

def main():

    q=queue.Queue(20)

    x=range(10)

    for n in x:

        tread=threading.Thread(target=read,args=(n,))

        twrite=threading.Thread(target=write,args=(n,))

        q.put(twrite)

        q.put(tread)

    x=range(20)

    for n in x:

        t=q.get()

 

        print('當前佇列中還有物件:' + str(q.qsize())+ '個\n')

 

        t.start()

        t.join()

 

    #q.join()

 

    print('主執行緒結束。')

 

if __name__=='__main__':

 

    main()

 

 

執行結果如下:

當前佇列中還有物件:19個

 

['寫入', '第0次']

 

當前佇列中還有物件:18個

 

讀取第0次['寫入第0次']

 

當前佇列中還有物件:17個

 

['寫入', '第1次']

 

當前佇列中還有物件:16個

 

讀取第1次['寫入第1次']

 

當前佇列中還有物件:15個

 

['寫入', '第2次']

 

當前佇列中還有物件:14個

 

讀取第2次['寫入第2次']

 

當前佇列中還有物件:13個

 

['寫入', '第3次']

 

當前佇列中還有物件:12個

 

讀取第3次['寫入第3次']

 

當前佇列中還有物件:11個

 

['寫入', '第4次']

 

當前佇列中還有物件:10個

 

讀取第4次['寫入第4次']

 

當前佇列中還有物件:9個

 

['寫入', '第5次']

 

當前佇列中還有物件:8個

 

讀取第5次['寫入第5次']

 

當前佇列中還有物件:7個

 

['寫入', '第6次']

 

當前佇列中還有物件:6個

 

讀取第6次['寫入第6次']

 

當前佇列中還有物件:5個

 

['寫入', '第7次']

 

當前佇列中還有物件:4個

 

讀取第7次['寫入第7次']

 

當前佇列中還有物件:3個

 

['寫入', '第8次']

 

當前佇列中還有物件:2個

 

讀取第8次['寫入第8次']

 

當前佇列中還有物件:1個

 

['寫入', '第9次']

 

當前佇列中還有物件:0個

 

讀取第9次['寫入第9次']

 

主執行緒結束。

 

從結果中看出,讀寫各十次都是成功的,且讀寫交替進行,符合同步要求,且讀寫沒有衝突。

 

五、  將檔案由兩個執行緒反覆同步寫和讀的實現由LifoQueue佇列來實現

程式碼如下:

importthreading

import queue

fromdatetime import datetime

from time import sleep

 

strf='1.txt'

 

def read(n):   

            with open(strf,'r',encoding='utf-8') as f:

                lstA=f.readlines()

           

            print('讀取第' + str(n) + '次' + str(lstA)  + '\n')



       

def write(n):

        with open(strf,'w',encoding='utf-8') as f:

            lstA=['寫入','第' + str(n) + '次']

            f.writelines(lstA)

        #sleep(1)

        print(str(lstA) +'\n') 

 

       

 

   

def main():

    x=range(10)

    q=queue.LifoQueue(20)

    for n in x :

        tread=threading.Thread(target=read,args=(n,))

        twrite=threading.Thread(target=write,args=(n,))

        q.put(tread)      

        q.put(twrite)

 

   

 

    x=range(q.maxsize)

    for n in x:

        t=q.get()

        t.start()

        t.join()

 

    print('主執行緒結束。')

 

if __name__=='__main__':

  

 

    main()

 

執行結果:

['寫入', '第9次']

 

讀取第9次['寫入第9次']

 

['寫入', '第8次']

 

讀取第8次['寫入第8次']

 

['寫入', '第7次']

 

讀取第7次['寫入第7次']

 

['寫入', '第6次']

 

讀取第6次['寫入第6次']

 

['寫入', '第5次']

 

讀取第5次['寫入第5次']

 

['寫入', '第4次']

 

讀取第4次['寫入第4次']

 

['寫入', '第3次']

 

讀取第3次['寫入第3次']

 

['寫入', '第2次']

 

讀取第2次['寫入第2次']

 

['寫入', '第1次']

 

讀取第1次['寫入第1次']

 

['寫入', '第0次']

 

讀取第0次['寫入第0次']

 

主執行緒結束。

 

 

 

——————————

今天整理的學習筆記完成,最後例行說明下我的自學思路:

根據過去多年我自學各種程式語言的經歷,認為只有真正體驗式,解決實際問題式的學習才會有真正的效果,即讓學習實際發生。在2004年的時候我開始在一個鄉村小學自學電腦 並學習vb6程式語言,沒有學習同伴,也沒有高師在上,甚至電腦都是孤島(鄉村那時還沒有網路),有的只是一本舊書,在痛苦的自學摸索中,我找到適應自己零基礎的學習方法:首先是每讀書的一小節就作相應的手寫筆記,第二步就是上機測試每一個筆記內容是否實現,其中會發現書中講的其實有出入或錯誤,第三步就是在上機測試之後,將筆記改為電子版,形成最終的修訂好的正確無誤的學習筆記。

通過反覆嘗試錯誤,在那個沒有分享與交流的黑暗時期我摸黑學會了VB6,爾後接觸了其它語言,也曾聽過付費視訊課程,結果發現也許自己學歷果然太低,就算是零基礎的入門課程,其實也難以跟上進度,講師的教學多數出現對初學者的實際情況並不瞭解的情況,況且學習者的個體也存在差異呢?當然更可怕的是收費課程的價格往往是自己難以承受的。

於是我的所有程式設計學習都改為了自學,繼續自己的三步學習筆記法的學習之路。

當然自學的最大問題是會走那麼多的彎路,沒有導師直接輸入式的教學來得直接,好在網路給我們帶來無限搜尋的機會,大家在網路上的學習日誌帶給我們共享交流的機會,而QQ群等交流平臺、網路社群的成立,我們可以一起自學,互相批評交流,也可以獲得更有效,更自主的自學成果。

於是我以人生已過半的年齡,決定繼續我的程式設計自學之路,開始學習python,只希望與大家共同交流,一個人的獨行是可怕的,只有一群人的共同前進才是有希望的。

誠摯期待您的交流分享批評指點!歡迎聯絡我加入從零開始的自學聯盟。

這個時代網際網路成為了一種基礎設施的存在,於是本來在孤獨學習之路上的我們變得不再孤獨,因為網路就是一個新的客廳,我們時刻都可以進行沙龍活動。

非常樂意能與大家一起交流自己自學心得和發現,更希望大家能夠對我學習過程中的錯誤給予指點——是的,這樣我就能有許多免費的高師了——這也是分享時代,社群時代帶來的好福利,我相信大家會的,是吧!

 

根據完全共享的精神,開源互助的理念,我的個人自學錄製過程是全部按4K高清視訊錄製的,從手寫筆記到驗證手寫筆記的上機操作過程全程錄製,但因為4K高清檔案太大均超過5G以上,所以無法上傳至網路,如有需要可聯絡我QQ578652607對傳,樂意分享。上傳分享到百度網盤的只是壓縮後的720P的視訊。

 

我的學習過程錄影百度盤地址分享如下:(清晰度:1280x720)

連結:https://pan.baidu.com/s/19BbmLmhXRgtdSXWMWtmabw

提取碼:dy3p

 

Bilibili:

https://www.bilibili.com/video/av38090801/

 

喜馬拉雅語音筆記:
https://www.ximalaya.com/keji/19103006/146250540


圖片

圖片