執行緒佇列,執行緒池,協程

2022-03-11 04:16:44 字數 4969 閱讀 3642

執行緒的queue,類似於程序

作用也是類似,queue(n)規範放入值的數量

這個和之前一樣是為了實現先進先出

import queue

q = queue.queue(2) # 括號內可加入數字規範放入值的數量,不加則不會規範

q.put('123')

q.put('qweqwe')

# q.put('111')

print(q.get())

print(q.get())

# print(q.get())

q.task_done()

q.join()

獲得的結果是先get到『123』

在這裡如果加入多的q.put程式會阻塞,queue.queue()則不會

這則可以實現先進後出的效果

import queue

q = queue.lifoqueue() #堆疊 先進後出

q.put('蕾姆')

q.put('炭治郎')

q.put('綾乃')

print(q.get())

print(q.get())

print(q.get())

結果為:

綾乃炭治郎

蕾姆執行緒定時器可以設定預設幾秒後開啟乙個執行緒,用t = timer(n,執行緒名)來表示

from threading import thread,timer

import time

def task():

print('執行緒執行了')

time.sleep(2)

print('執行緒結束了')

t = timer(4,task) # 過了4s後開啟了乙個執行緒

t.start()

# print('hyc')

程序池執行緒池:

池的功能限制程序數或執行緒數.

什麼時候限制?

當併發的任務數量遠遠大於計算機所能承受的範圍,即無法一次性開啟過多的任務數量

就應該考慮去限制程序數或執行緒數,從保證伺服器不崩.

from concurrent.futures import processpoolexecutor,threadpoolexecutor

from threading import currentthread

from multiprocessing import current_process

import time

def task(i):

print(f' 在執行任務 ')

# print(f'程序 在執行任務 ')

time.sleep(1)

return i**2

if __name__ == '__main__':

pool = threadpoolexecutor(4) # 池子裡只有4個執行緒

# pool = processpoolexecutor(4) # 池子裡只有4個執行緒

fu_list =

for i in range(20):

# pool.submit(task,i) # task任務要做20次,4個執行緒負責做這個事

future = pool.submit(task,i) # task任務要做20次,4個程序負責做這個事

# print(future.result()) # 如果沒有結果一直等待拿到結果,導致了所有的任務都在序列

pool.shutdown() # 關閉了池的入口,會等待所有的任務執行完,結束阻塞.

for fu in fu_list:

print(fu.result())

理解為提交任務的兩種方式

同步: 提交了乙個任務,必須等任務執行完了(拿到返回值),才能執行下一行**,

非同步: 提交了乙個任務,不要等執行完了,可以直接執行下一行**.

from concurrent.futures import processpoolexecutor,threadpoolexecutor

from threading import currentthread

from multiprocessing import current_process

import time

def task(i):

print(f' 在執行任務 ')

# print(f'程序 在執行任務 ')

time.sleep(1)

return i**2

def parse(future):

# 處理拿到的結果

print(future.result())

if __name__ == '__main__':

pool = threadpoolexecutor(4) # 池子裡只有4個執行緒

# pool = processpoolexecutor(4) # 池子裡只有4個執行緒

fu_list =

for i in range(20):

# pool.submit(task,i) # task任務要做20次,4個執行緒負責做這個事

future = pool.submit(task,i) # task任務要做20次,4個程序負責做這個事

future.add_done_callback(parse)

# 為當前任務繫結了乙個函式,在當前任務執行結束的時候會觸發這個函式,

# 會把future物件作為引數傳給函式

# 這個稱之為**函式,處理完了回來就呼叫這個函式.

# print(future.result()) # 如果沒有結果一直等待拿到結果,導致了所有的任務都在序列

# pool.shutdown() # 關閉了池的入口,會等待所有的任務執行完,結束阻塞.

# for fu in fu_list:

# print(fu.result())

python的執行緒用的是作業系統原生的執行緒

協程:單執行緒下實現併發

併發:切換+儲存狀態

多執行緒:作業系統幫你實現的,如果遇到io切換,執行時間過長也會切換,實現乙個雨露均沾的效果.

什麼樣的協程是有意義的?

遇到io切換的時候才有意義

具體:協程概念本質是程式設計師抽象出來的,作業系統根本不知道協程存在,也就說來了乙個執行緒我自己遇到io 我自己執行緒內部直接切到自己的別的任務上了,作業系統跟本發現不了,

也就是實現了單執行緒下效率最高.

優點:自己控制切換要比作業系統切換快的多

缺點:對比多執行緒

自己要檢測所有的io,但凡有乙個阻塞整體都跟著阻塞.

對比多程序

無法利用多核優勢.

為什麼要有協程(遇到io切換)?

自己控制切換要比作業系統切換快的多.降低了單個執行緒的io時間,

我們可以用協程來寫乙個沒有io的**

import time

def eat():

print('eat 1')

# 瘋狂的計算呢沒有io

time.sleep(2)

# for i in range(100000000):

# i+1

def play():

print('play 1')

# 瘋狂的計算呢沒有io

time.sleep(3)

# for i in range(100000000):

# i+1

play()

eat() # 5s

import time

def func1():

while true:

1000000+1

yield

def func2():

g = func1()

for i in range(100000000):

i+1next(g)

start = time.time()

func2()

stop = time.time()

print(stop - start)

它執行用了22秒的時間

如果我們不用協程去完成它會怎麼樣呢

import time

def func1():

for i in range(100000000):

i+1def func2():

for i in range(100000000):

i+1start = time.time()

func1()

func2()

stop = time.time()

print(stop - start) # 8.630893230438232

只用了8秒

可見,在沒有io的情況下,不建議用協程。相反,有大量io的時候,協程就比較佔優勢了。而我們平時敲得**都含有大量的io

from gevent import monkey;monkey.patch_all() #打了乙個補丁,可以實現捕獲非gevent的io.

import gevent

import time

def eat():

print('eat 1')

time.sleep(2)

print('eat 2')

def play():

print('play 1')

# 瘋狂的計算呢沒有io

time.sleep(3)

print('play 2')

start = time.time()

g1 = gevent.spawn(eat)

g2 = gevent.spawn(play)

g1.join()

g2.join()

end = time.time()

print(end-start) # 3.0040290355682373

執行緒佇列 執行緒池 協程

1 執行緒佇列 from multiprocessing queue joinablequeue 程序ipc佇列 from queue import queue 執行緒佇列 先進先出 from queue import lifoqueue 後進先出的 方法都是一樣的 put get put nowa...

python執行緒池 協程

python的執行緒雖然是真正的執行緒,但直譯器執行 時,有乙個gil鎖 global interpreter lock,任何python執行緒執行前,必須先獲得gil鎖,然後,每執行100條位元組碼,直譯器就自動釋放gil鎖,讓別的執行緒有機會執行。這個gil全域性鎖實際上把所有執行緒的執行 都給...

併發程式設計 執行緒池程序池協程

1.socket服務端實現併發 現在回來想網路程式設計服務端需要滿足哪幾點需求 2.程序池執行緒池介紹 執行緒不可能無限制的開下去,總要消耗和占用資源 程序池執行緒池概念 硬體有極限,為了減輕硬體壓力,所以有了池的概念 注意協程這個概念完全是程式設計師自己想出來的東西,它對於作業系統來說根本不存在。...