程序池和執行緒池 協程 TCP單執行緒實現併發

2022-01-21 23:09:14 字數 3962 閱讀 6401

一、程序池和執行緒池

當被操作物件數目不大時,我們可以手動建立幾個程序和執行緒,十幾個幾十個還好,但是如果有上百個上千個。手動操作麻煩而且電腦硬體跟不上,可以會崩潰,此時程序池、執行緒池的功效就能發揮了。我們可以通過維護乙個程序池、執行緒池來控制程序數目和執行緒數目。在保證計算機硬體安全的情況下最大限度的利用計算機,池其實是降低了程式的執行效率,但是保證了計算機硬體的安全。

注意點:在使用程序池、執行緒池,pool可以提供指定數量的程序,執行緒,供使用者呼叫,當有新的請求提交到pool中時,如果池還沒有滿,那麼就會建立乙個新的程序,執行緒用來執行該請求,但如果池中的程序,執行緒數量已經達到規定的最大值,那麼該請求就會等待,直到池中有程序,執行緒結束,就重新使用程序池、執行緒池中的程序,執行緒。

池子中建立的程序/執行緒建立一次就不會再建立了,至始至終都是使用最初的那幾個,這樣的話節省了反覆開闢程序/執行緒的資源(******)

主要方法:

pool.submit(task,1)     #

朝池子中提交任務 非同步提交 task是函式,1是task的引數

pool.shutdown() #

關閉池子 等待池子中所有任務執行完畢之後才會往下執行**

執行緒池和程序池建立的方法一樣只是匯入的模組不一樣

**函式add_done_callback,我們可以把耗時間(io操作)的任務放在程序池中,然後指定**函式(主程序負責執行),這樣主程序在執行**函式時就省去了io的過程,直接拿到的是任務的結果。

非同步**機制:當非同步提交的任務有返回結果之後,會自動觸發**函式的執行。

from concurrent.futures import

threadpoolexecutor,processpoolexecutor

import

time

importos#

pool = threadpoolexecutor(5) 建立執行緒池 # 括號內可以傳引數指定執行緒池內的執行緒個數

也可以不傳 不傳預設是當前所在計算機的cpu個數乘5

pool = processpoolexecutor() 建立程序池 #

預設是當前計算機cpu的個數

deftask(n):

print(n,os.getpid()) #

檢視當前程序號

time.sleep(2)

return n**2

defcall_back(n):

print('

拿到了非同步提交任務的返回結果:

',n.result()) #submit提交任務返回值,需要result才能獲取結果

"""非同步**機制:當非同步提交的任務有返回結果之後,會自動觸發**函式的執行

"""if

__name__ == '

__main__':

for i in range(20):

pool.submit(task,i).add_done_callback(call_back)

#提交任務的時候 繫結乙個**函式 一旦該任務有結果 立刻執行對於的**函式

#submit提交任務task函式,當有返回值時,立刻把返回值傳入**函式

二、協程

協程就是單執行緒下實現併發 ,協程:完全是程式設計師自己想出來的乙個名詞

程式設計師通過自己**檢測程式中的io操作,一旦遇到io自己通過**切換,給作業系統的感覺是你這個執行緒沒有任何的io,從而保證程式在執行態和就緒態來回切換,提公升**的執行效率。

切換+儲存狀態就一定能夠提公升效率嗎???

當你的任務是io密集型的情況下    會提公升效率

當你的任務是計算密集型時       會降低效率

spawn會自動幫你檢測任務有沒有i/o,碰到i/o就切換

from gevent import monkey;monkey.patch_all()  #

由於該模組經常被使用 所以建議寫成一行

from gevent import

spawn

import

time

"""注意gevent模組沒辦法自動識別time.sleep等io情況

需要你手動再配置乙個引數 monkey

"""def

heng():

print("哼"

) time.sleep(2)

print('哼'

)def

ha():

print('哈'

) time.sleep(3)

print('哈'

)def

heiheihei():

print('

嘿嘿嘿'

) time.sleep(5)

print('

嘿嘿嘿'

)start =time.time()

g1 =spawn(heng)

g2 = spawn(ha) #

spawn會檢測所有的任務

g3 =spawn(heiheihei)

g1.join()

g2.join()

g3.join()

print(time.time() -start)#結果

哼哈嘿嘿嘿哼

哈嘿嘿嘿

5.012551546096802

三、tcp單執行緒實現併發

服務端

from gevent import

monkey;monkey.patch_all()

import

socket

from gevent import

spawn

server =socket.socket()

server.bind((

'127.0.0.1

',8080))

server.listen(5)

deftalk(conn):

while

true:

try:

data = conn.recv(1024)

if len(data) == 0:break

print(data.decode('

utf-8'))

conn.send(data.upper())

except

connectionreseterror as e:

print

(e)

break

conn.close()

defserver1():

while

true:

conn, addr =server.accept()

spawn(talk,conn)

if__name__ == '

__main__':

g1 =spawn(server1)

g1.join()

客戶端  實現400個執行緒,模擬400個使用者

import

socket

from threading import

thread,current_thread

defclient():

client =socket.socket()

client.connect((

'127.0.0.1

',8080))

n =0

while

true:

data = '

%s %s

'%(current_thread().name,n)

client.send(data.encode(

'utf-8'))

res = client.recv(1024)

print(res.decode('

utf-8'))

n += 1

for i in range(400):

t = thread(target=client)

t.start()

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

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

單執行緒記憶體池

1 單執行緒記憶體池 記憶體池的基本思想是大塊向系統申請記憶體,內部切割為小塊,內部 cache 之後有選擇的分配,不夠的時候繼續向系統大塊申請記憶體,示例 如下 struct tm memblock class tm pool void tm pool newobj tm bufunit head...

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

執行緒的queue,類似於程序 作用也是類似,queue n 規範放入值的數量 這個和之前一樣是為了實現先進先出 import queue q queue.queue 2 括號內可加入數字規範放入值的數量,不加則不會規範 q.put 123 q.put qweqwe q.put 111 print ...