線程是屬於進程的,線程運行在進程空間內,同一進程所產生的線程共享同一內存空間,當進程退出時該進程所產生的線程都會被強制退出並清除。線程可與屬於同一進程的其它線程共享進程所擁有的所有資源,可是其自己基本上不擁有系統資源,只擁有一點在運行中必不可少的信息(如程序計數器、一組寄存器和棧)。html
進程就是一個程序在一個數據集上的一次動態執行過程。 進程通常由程序、數據集、進程控制塊三部分組成。咱們編寫的程序用來描述進程要完成哪些功能以及如何完成;數據集則是程序在執行過程當中所須要使用的資源;進程控制塊用來記錄進程的外部特徵,描述進程的執行變化過程,系統能夠利用它來控制和管理進程,它是系統感知進程存在的惟一標誌。python
進程和線程的目的:提升執行效率git
一、單進程單線程,主進程、主線程
二、自定義線程:
主進程
主線程
子線程github
建立多進程,目的是爲了利用CPU的多核,讓CPU同時執行多個任務。編程
進程:
優勢:同時利用多個CPU,可以同時進行多個操做
缺點:耗費資源(建立時從新開闢內存空間)api
線程:
優勢:共享同一進程內存,IO操做時,不依賴CPU,可併發操做
缺點:搶佔資源瀏覽器
進程、線程越多越好嗎?
進程不是越多越好,通常而言,CPU個數 = 進程個數
線程數,依賴任務而定,不是越多越好,每次記錄線程的請求信息,上下文切換耗時。安全
IO密集型操做(不用CPU):多線程
計算密集型操做(使用CPU):多進程網絡
python的進程上有個GIL 全局解釋性鎖,這個會形成,一個進程的多個線程,不能同時使用多個cpu,而是cpu每次只能選一個線程執行,所以,多線程在cpu執行的是無效的。可是在I/O操做的時候是能夠同步的,好比time.sleep就是io 操做,多線程,能夠同時等待多線程
主線程
好比咱們寫的py文件,執行的時候,全部代碼是如何向下執行呢?確定有個主線程的。
再咱們建立多線程時候,這些線程都是子線程,那確定有個主線程的。
進程和程序關係 進程:程序實例,程序子集,有所謂生命週期,能夠kill掉,好比你安裝的word,是一個程序,你打開一個文檔是一個進程,能夠關掉。 進程要想完成併發執行的功能,就要進程切換。進程切換,上下文切換,運行進程,說明在cpu的寄存器裏面有數據了。
Python的多線程或多進程的調度是經過操做系統的調度程序實現的。當一個線程或進程阻塞,例如等待IO時,該線程或進程被操做系統下降執行的優先級,CPU內核能夠被分配用來執行其它有實際計算任務的線程或進程。
Python的線程或進程架構:
線程存在於進程以內。一個進程能夠包含多個線程,但一般包含至少一個線程,這個線程被稱爲主線程。在一個進程內的線程共享進程的內存,因此進程內的不一樣線程的通訊能夠經過引用共享的對象來實現。不一樣的進程並不共享同一塊內存,因此進程間的通訊是經過其它接口如文件、sockets或特別分配的共享內存區域來實現的。
當線程須要執行操做時,它請求操做系統的線程調度程序給其分配一些CPU時間。調度程序根據各類參數來將CPU的核心分配給等待的線程,調度程序的實現根據操做系統的不一樣而不一樣。同一個進程中運行的不一樣線程可能同時運行在不一樣的CPU核心上(但CPython例外)。
Python的CPython解釋器包含一個全局解釋器鎖Global Interpreter Lock(GIL),它的存在確保了Python進程中同時只有一個線程能夠執行,即便有多個CPU核心可用。因此CPython程序中的多線程並不能經過多個cpu核心並行執行。不過,即便是這樣,在等待I/O時被阻塞的線程仍然被操做系統下降執行優先級並放入背景等待,以便讓真正有計算任務的線程能夠執行,下圖簡單地描述了這個過程:
上圖中的Waiting for GIL狀態是某個線程已經完成了I/O,在退出阻塞狀態想要開始執行時,另一個線程持有GIL,因此已經就緒的線程被強制等待。在不少的網絡應用程序中,花在等待I/O上的時間比實際處理數據的時間要多得多。只要不是有很是大的併發鏈接數,由GIL致使的鏈接的線程的阻塞是相對較低的,因此對於這些網絡服務程序,使用線程的方式實現併發鏈接,仍然是一個合適的架構。
對於操做系統來講,一個應用就是一個進程。好比打開一個瀏覽器,它是一個進程;打開一個記事本,它是一個進程。每一個進程有它特定的進程號。他們共享操做系統的內存資源。進程是操做系統分配資源的最小單位。
而對於每個進程而言,好比一個視頻播放器,它必須同時播放視頻和音頻,就至少須要同時運行兩個「子任務」,進程內的這些子任務就是經過線程來完成。線程是計算機執行任務的最小單元。一個進程它能夠包含多個線程,這些線程相互獨立,同時又共享進程所擁有的資源。
以使用OS資源的角度來講,進程比線程更加「重量級」,建立一個新的進程須要的時間比建立一個新線程來講要多,並且進程使用更多的內存資源。
有一點須要注意的是,若是你須要執行一個計算任務密集的Python程序,最好是經過多進程來實現。由於若是程序中的每一個線程都有繁重的計算任務,它們都要使用CPU,而因爲GIL的存在,這些線程並不能真正的在不一樣的CPU核心上並行執行,因此這會嚴重下降程序總體的性能。
Python中的多線程通常是經過其內置的threading模塊提供的接口來實現的,多進程是經過multiprocessing模塊實現的。本篇的代碼實例是基於Python3的。
Python多進程編程
在Python中,經過multiprocessing模塊內的Process類來建立新的進程。例如:
from multiprocessing import Process import os def info(title): print(title) print('module name:', __name__) if hasattr(os, 'getppid'): # only available on Unix print('parent process:', os.getppid()) print('process id:', os.getpid()) def f(name): info('function f') print('hello', name) if __name__ == '__main__': info('main line') p = Process(target=f, args=('bob',)) p.start() p.join() """ main line module name: __main__ parent process: 2128 process id: 3688 function f module name: __mp_main__ parent process: 3688 process id: 6884 hello bob """
經過Process類中的start方法來啓動新的進程。有三種不一樣的啓動方式:spawn,fork和forkserver。這三種方式的詳細區別請參考官方文檔。
Process類中的join方法的做用是等待子進程結束後再繼續往下執行。
multiprocessing模塊內包括兩種進程間通訊的方式:Queues和Pipes;同時也提供了其它方式在進程間共享狀態,不過官方文檔也提到在併發程序設計中儘可能避免這種方式。
先來看一下Queues的例子:
from multiprocessing import Process, Queue def f(q): q.put([42, None, 'hello']) if __name__ == '__main__': q = Queue() p = Process(target=f, args=(q,)) p.start() print(q.get()) # prints "[42, None, 'hello']" p.join() """ [42, None, 'hello'] """
multiprocessing模塊中的Queue幾乎是queue.Queue的克隆,而且Queues是線程和進程安全的,這意味着多個線程或進程訪問同一個Queue實例時,不會出現數據混亂的情況。下面來看一個使用Pipe的例子:
from multiprocessing import Process, Pipe def f(conn): conn.send([42, None, 'hello']) conn.close() if __name__ == '__main__': parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn,)) p.start() print(parent_conn.recv()) # prints "[42, None, 'hello']" p.join() """ [42, None, 'hello'] """
Pipe方法返回一對鏈接對象,表明管道的兩端,每一個鏈接對象都有send()和recv()方法。若是不一樣的進程(或線程)在同一時刻試圖在管道的同一端進行讀寫,數據可能會出現混亂,在不一樣端是沒有問題的。Python中的對象大部分都不是進程(或線程)安全的,因此在不一樣的進程(或線程)操做同一對象時,須要使用同步機制。
進程的同步是經過Lock實現的。實例以下:
from multiprocessing import Process, Lock def f(l, i): l.acquire() try: print('hello world', i) finally: l.release() if __name__ == '__main__': lock = Lock() for num in range(10): Process(target=f, args=(lock, num)).start() """ hello world 1 hello world 3 hello world 0 hello world 2 hello world 7 hello world 6 hello world 4 hello world 8 hello world 9 hello world 5 """
Pool類提供了一個批量建立多個子進程的方法,能夠給定子進程數的上限,避免無限地消耗系統的資源。看一下官方文檔的實例:
from multiprocessing import Pool, TimeoutError import time import os def f(x): return x*x if __name__ == '__main__': # start 4 worker processes with Pool(processes=4) as pool: # print "[0, 1, 4,..., 81]" print(pool.map(f, range(10))) # print same numbers in arbitrary order for i in pool.imap_unordered(f, range(10)): print(i) # evaluate "f(20)" asynchronously res = pool.apply_async(f, (20,)) # runs in *only* one process print(res.get(timeout=1)) # prints "400" # evaluate "os.getpid()" asynchronously res = pool.apply_async(os.getpid, ()) # runs in *only* one process print(res.get(timeout=1)) # prints the PID of that process # launching multiple evaluations asynchronously *may* use more processes multiple_results = [pool.apply_async(os.getpid, ()) for i in range(4)] print([res.get(timeout=1) for res in multiple_results]) # make a single worker sleep for 10 secs res = pool.apply_async(time.sleep, (10,)) try: print(res.get(timeout=1)) except TimeoutError: print("We lacked patience and got a multiprocessing.TimeoutError") print("For the moment, the pool remains available for more work") # exiting the 'with'-block has stopped the pool print("Now the pool is closed and no longer available") """ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 0 1 4 9 16 25 36 49 64 81 400 8652 [8652, 8652, 8652, 8652] We lacked patience and got a multiprocessing.TimeoutError For the moment, the pool remains available for more work Now the pool is closed and no longer available """
Python中使用線程的方式有不少都與使用進程的方式相似,這裏就再也不列出實例代碼。
在Python中,經過threading模塊內的Thread類來建立新的進程。經過Thread類中的start方法啓動線程,join方法等待線程結束。
線程間最簡單的通訊方式是經過threading模塊內的Event類。固然也能夠經過共享對象來在線程間共享狀態信息。因爲queue.Queue是線程和進程安全的,因此它也是線程通訊使用理想對象。其它對象大部分都不是線程(或進程)安全的,因此在不一樣的線程(或進程)操做同一對象時,須要使用同步機制。
threading模塊中提供了Lock,RLock,Condition,Semaphore等類進行線程間的同步。
關於threading模塊中更詳細的使用信息,請參考官方文檔。
內容來源與參考:
https://andyyoung01.github.io/2017/01/21/Python%E7%9A%84%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8E%E5%A4%9A%E8%BF%9B%E7%A8%8B%E7%AE%80%E4%BB%8B-%E4%B8%8A/#Python的線程和GIL
https://andyyoung01.github.io/2017/01/22/Python%E7%9A%84%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8E%E5%A4%9A%E8%BF%9B%E7%A8%8B%E7%AE%80%E4%BB%8B-%E4%B8%8B/
threading 模塊創建在 _thread 模塊之上。thread 模塊以低級、原始的方式來處理和控制線程,而 threading 模塊經過對 thread 進行二次封裝,提供了更方便的 api 來處理線程。
threading基於Java的線程模型設計。鎖(Lock)和條件變量(Condition)在Java中是對象的基本行爲(每個對象都自帶了鎖和條件變量),而在Python中則是獨立的對象,因此python的threading模塊中還提供了Lock,Rlock,Condition,Event等經常使用類,它們在python中是獨立於Tread模塊的,可是卻與線程緊密相關,不可分割。
須要注意的是:python的線程中沒有優先級、線程組,也不能被中止、暫停、恢復、中斷,線程只能隨着線程中的代碼執行完畢而被銷燬。在實現線程池的時候沒法中止已經注入了方法且執行超時的線程。
import threading import time def worker(num): time.sleep(3) print("Thread %d" % num) return for i in range(5): t = threading.Thread(target=worker, args=(i,)) t.start() """ Thread 0 Thread 1 Thread 2 Thread 4 Thread 3 """
import threading import time class MyThread(threading.Thread): def __init__(self, name): # threading.Thread.__init__(self) super(MyThread, self).__init__(target=self.fun, name="t %d" % i) self.name = name def fun(self): time.sleep(2) print("name %s thread %s" % (self.name, threading.current_thread().name)) for i in range(5): t = MyThread(i) t.start() """ name 0 thread 0 name 2 thread 2 name 1 thread 1 name 4 thread 4 name 3 thread 3 """
t.start() : 激活線程,
t.getName() : 獲取線程的名稱
t.setName() : 設置線程的名稱
t.name : 獲取或設置線程的名稱
t.is_alive() : 判斷線程是否爲激活狀態
t.isAlive() :判斷線程是否爲激活狀態
t.setDaemon() 設置爲後臺線程或前臺線程(默認:False);經過一個布爾值設置線程是否爲守護線程,必須在執行start()方法以後纔可使用。若是是後臺線程,主線程執行過程當中,後臺線程也在進行,主線程執行完畢後,後臺線程不論成功與否,均中止;若是是前臺線程,主線程執行過程當中,前臺線程也在進行,主線程執行完畢後,等待前臺線程也執行完成後,程序中止
t.isDaemon() : 判斷是否爲守護線程
t.ident :獲取線程的標識符。線程標識符是一個非零整數,只有在調用了start()方法以後該屬性纔有效,不然它只返回None。
t.join() :逐個執行每一個線程,執行完畢後繼續往下執行,該方法使得多線程變得無心義
t.run() :線程被cpu調度後自動執行線程對象的run方法
join 代碼
import time import threading def printNum(a): print('num:',a) time.sleep(1) def ThreadTest(i): return threading.Thread(target=printNum, args=(999,)) thread_arr = [] for i in range(5): t = ThreadTest(i) thread_arr.append(t) for t in thread_arr: t.start() for t in thread_arr: t.join() print('finished') """ num: 999 num: 999 num: 999 num: 999 num: 999 finished """
threading用於提供線程相關的操做,線程是應用程序中工做的最小單元。python當前版本的多線程庫沒有實現優先級、線程組,線程也不能被中止、暫停、恢復、中斷。
threading模塊提供的類:
Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local。
threading 模塊提供的經常使用方法:
threading.currentThread(): 返回當前的線程變量。
threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啓動後、結束前,不包括啓動前和終止後的線程。
threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
threading 模塊提供的常量:
threading.TIMEOUT_MAX 設置threading全局超時時間。
Thread是線程類,有兩種使用方法,直接傳入要運行的方法或從Thread繼承並覆蓋run():
import threading import time # 方法一:將要執行的方法做爲參數傳給Thread的構造方法 def action(arg): time.sleep(1) print('the arg is:%s\r' % arg) for i in range(4): t = threading.Thread(target=action, args=(i,)) t.start() print('main thread end!') """ main thread end! the arg is:0 the arg is:3 """ # 方法二:從Thread繼承,並重寫run() class MyThread(threading.Thread): def __init__(self, arg): super(MyThread, self).__init__() # 注意:必定要顯式的調用父類的初始化函數。 self.arg = arg def run(self): # 定義每一個線程要運行的函數 time.sleep(1) print('the arg is:%s\r' % self.arg) for i in range(4): t = MyThread(i) t.start() print('main thread end!') """ main thread end! the arg is:1 the arg is:2 the arg is:3 """
因爲線程之間隨機調度:某線程可能在執行n條後,CPU接着執行其餘線程。爲了多個線程同時操做一個內存中的資源時不產生混亂,咱們使用鎖。
Lock(指令鎖)是可用的最低級的同步指令。Lock處於鎖定狀態時,不被特定的線程擁有。Lock包含兩種狀態——鎖定和非鎖定,以及兩個基本的方法。
能夠認爲Lock有一個鎖定池,當線程請求鎖定時,將線程置於池中,直到得到鎖定後出池。池中的線程處於狀態圖中的同步阻塞狀態。
RLock(可重入鎖)是一個能夠被同一個線程請求屢次的同步指令。RLock使用了「擁有的線程」和「遞歸等級」的概念,處於鎖定狀態時,RLock被某個線程擁有。擁有RLock的線程能夠再次調用acquire(),釋放鎖時須要調用release()相同次數。
能夠認爲RLock包含一個鎖定池和一個初始值爲0的計數器,每次成功調用 acquire()/release(),計數器將+1/-1,爲0時鎖處於未鎖定狀態。
簡言之:Lock屬於全局,Rlock屬於線程。
構造方法:
Lock(),Rlock(),推薦使用Rlock()
實例方法:
acquire([timeout]): 嘗試得到鎖定。使線程進入同步阻塞狀態。
release(): 釋放鎖。使用前線程必須已得到鎖定,不然將拋出異常。
線程鎖threading.RLock和threading.Lock
咱們使用線程對數據進行操做的時候,若是多個線程同時修改某個數據,可能會出現不可預料的結果,爲了保證數據的準確性,引入了鎖的概念。
例:假設列表A的全部元素就爲0,當一個線程從前向後打印列表的全部元素,另一個線程則從後向前修改列表的元素爲1,那麼輸出的時候,列表的元素就會一部分爲0,一部分爲1,這就致使了數據的不一致。鎖的出現解決了這個問題。
View Code
Lock與Rlock 對比
import threading lock = threading.Lock() #Lock對象 lock.acquire() lock.acquire() #產生了死鎖。 lock.release() lock.release() import threading rLock = threading.RLock() #RLock對象 rLock.acquire() rLock.acquire() #在同一線程內,程序不會堵塞。 rLock.release() rLock.release() lock vs rlock Code
未使用鎖
屢次運行可能產生混亂。這種場景就是適合使用鎖的場景。
import threading import time gl_num = 0 def show(arg): global gl_num time.sleep(0.00001) gl_num += 1 print(gl_num) for i in range(5): t = threading.Thread(target=show, args=(i,)) t.start() print('main thread stop') """ 1 2 3 main thread stop 4 5 """
使用鎖
全局變量在每次被調用時都要得到鎖,才能操做,所以保證了共享數據的安全性。
import threading import time gl_num = 0 lock = threading.RLock() # 調用acquire([timeout])時,線程將一直阻塞,直到得到鎖定或者直到timeout秒後(timeout參數可選)。 # 返回是否得到鎖。 def Func(): lock.acquire() global gl_num gl_num += 1 time.sleep(0.00001) print(gl_num) lock.release() for i in range(5): t = threading.Thread(target=Func) t.start() """ 1 2 3 4 5 """
條件變量對象能讓一個線程停下來,等待其它線程知足了某個「條件」。如,狀態的改變或值的改變。
Condition(條件變量)一般與一個鎖關聯。須要在多個Contidion中共享一個鎖時,能夠傳遞一個Lock/RLock實例給構造方法,不然它將本身生成一個RLock實例。
能夠認爲,除了Lock帶有的鎖定池外,Condition還包含一個等待池,池中的線程處於等待阻塞狀態,直到另外一個線程調用notify()/notifyAll()通知;獲得通知後線程進入鎖定池等待鎖定。
一個condition變量老是與某些類型的鎖相聯繫,這個可使用默認的狀況或建立一個,當幾個condition變量必須共享和同一個鎖的時候,是頗有用的。鎖是conditon對象的一部分:沒有必要分別跟蹤。
condition變量服從上下文管理協議:with語句塊封閉以前能夠獲取與鎖的聯繫。 acquire() 和 release() 會調用與鎖相關聯的相應的方法。
其餘和鎖關聯的方法必須被調用,wait()方法會釋放鎖,當另一個線程使用 notify() or notify_all()喚醒它以前會一直阻塞。一旦被喚醒,wait()會從新得到鎖並返回
Condition(lock=None)
構造方法:
Condition([lock/rlock])
實例方法:
比較經典的例子是生產者與消費者模型,代碼中寫了兩個類,Consumer和Producer,分別繼承了Thread類,分別初始化這兩個類得到了c和p對象,並啓動這兩個線程。則這兩個線程去執行run方法(這裏與Thread類內部的調度有關),定義了producer全局變量和condition對象爲全局變量,當producer不大於1時,消費者線程被condition對象阻塞,不能繼續消費(這裏是再也不遞減),當producer不小於10時,生產者線程被condition對象阻塞,再也不生產(這裏是再也不累加),代碼在下面,拿去執行,斷點一下就明白了。
import threading import time condition = threading.Condition() products = 0 class Producer(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global condition, products while True: if condition.acquire(): if products < 10: products += 1; print("Producer(%s):deliver one, now products:%s" %(self.name, products)) condition.notify() else: print("Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products)) condition.wait(); condition.release() time.sleep(2) class Consumer(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global condition, products while True: if condition.acquire(): if products > 1: products -= 1 print("Consumer(%s):consume one, now products:%s" %(self.name, products)) condition.notify() else: print("Consumer(%s):only 1, stop consume, products:%s" %(self.name, products)) condition.wait(); condition.release() time.sleep(2) if __name__ == "__main__": for p in range(0, 2): p = Producer() p.start() for c in range(0, 10): c = Consumer() c.start() """ Producer(Thread-1):deliver one, now products:1 Producer(Thread-2):deliver one, now products:2 Consumer(Thread-3):consume one, now products:1 Consumer(Thread-4):only 1, stop consume, products:1 Consumer(Thread-5):only 1, stop consume, products:1 ..... """
通用的條件變量。多個線程能夠等待某個事件的發生,在事件發生後,全部的線程都會被激活。
Event(事件)是最簡單的線程通訊機制之一:一個線程通知事件,其餘線程等待事件。Event內置了一個初始爲False的標誌,當調用set()時設爲True,調用clear()時重置爲 False。wait()將阻塞線程至等待阻塞狀態。
Event其實就是一個簡化版的 Condition。Event沒有鎖,沒法使線程進入同步阻塞狀態。
構造方法:
Event()
實例方法:
這是一個比較關鍵的類,它的意義在於能夠控制屬於同一個線程類的多個實例化對象,讓他們同時阻塞或者執行。配合隊列來實現一個線程池很是好用。
import threading import time import random def light(): if not event.isSet(): #沒有設置的話 event.set() # 設置綠燈 count = 0 #計數器秒數 while True: if count < 10: #小於十秒 是綠燈 print("\033[42;1m ------green light on ----\033[0m") elif count < 13: #小於13秒 大於10秒 是黃燈 print("\033[43;1m ------yellow light on ----\033[0m") elif count < 20: #小於於20秒 有設置則取消 if event.isSet(): event.clear() print("\033[41;1m ------red light on ----\033[0m") else: #大於20 從新 count = 0 #取消秒數計時 event.set() #從新變爲綠燈 time.sleep(1) count +=1 def car(n): # 第二個線程 車線程 while 1: time.sleep(random.randrange(3)) #隨機等待三秒 if event.isSet(): print("car [%s] is running..." % n) #若是被設置了信號則是綠燈,該線程的車便可經過 else: #不然的話提示紅燈 print("car [%s] is waitting for the red light.." %n) event.wait() #紅燈的話,會在此處卡住,不往下執行 print("Green light is on ,car %s is running......." %n) if __name__ == '__main__': #下面是定義了兩個線程 ,燈線程 車線程, threading.Event用來設置標着符號讓兩個線程交流 event = threading.Event() Light = threading.Thread(target=light) Light.start() for i in range(3): t = threading.Thread(target=car,args=(i,)) t.start() """ ------green light on ---- car [2] is running... car [0] is running... ------yellow light on ---- car [1] is running... car [1] is running... car [2] is running... car [0] is running... ------red light on ---- car [1] is waitting for the red light.. ...... """
Queue 就是對隊列,它是線程安全的
舉例來講,咱們去肯德基吃飯。廚房是給咱們作飯的地方,前臺負責把廚房作好的飯賣給顧客,顧客則去前臺領取作好的飯。這裏的前臺就至關於咱們的隊列。
這個模型也叫生產者-消費者模型。
import queue q = queue.Queue(maxsize=0) # 構造一個先進先出隊列,maxsize指定隊列長度,爲0 時,表示隊列長度無限制。 q.join() # 等到隊列爲空的時候,再執行別的操做 q.qsize() # 返回隊列的大小 (不可靠) q.empty() # 當隊列爲空的時候,返回True 不然返回False (不可靠) q.full() # 當隊列滿的時候,返回True,不然返回False (不可靠) q.put(item, block=True, timeout=None) # 將item放入Queue尾部,item必須存在,能夠參數block默認爲True,表示當隊列滿時,會等待隊列給出可用位置。爲False時爲非阻塞,此時若是隊列已滿,會引起queue.Full 異常。 可選參數timeout,表示 會阻塞設置的時間,事後,若是隊列沒法給出放入item的位置,則引起 queue.Full 異常 q.get(block=True, timeout=None) # 移除並返回隊列頭部的一個值,可選參數block默認爲True,表示獲取值的時候,若是隊列爲空,則阻塞,爲False時,不阻塞,若此時隊列爲空,則引起 queue.Empty異常。 可選參數timeout,表示會阻塞設置的時候,事後,若是隊列爲空,則引起Empty異常。 q.put_nowait(item) # 等效於 put(item,block=False) q.get_nowait() # 等效於 get(item,block=False)