python 內置的線程池、進程池及其並發服務器的實現


python 內置的線程池、進程池及其並發服務器的實現

內置線程池

 1 from multiprocessing.pool import ThreadPool  # 導入線程池
 2 import time
 3 w_start = time.time()
 4 def worker():
 5     time.sleep(3)
 6     print('55555')
 7 pool = ThreadPool(2)  # 參數是線程池的數量,默認為1
 8 pool.apply_async(worker)
 9 pool.apply_async(worker)
10 pool.apply_async(worker)
11 pool.close()  # 關閉線程池 不再提交任務
12 pool.join()  # 等待線程池里面的任務執行完畢
13 print(time.time() - w_start)
14 ############### 運行結果:##########
15 55555
16 55555
17 55555
18 6.055918216705322

這里運行了6秒是因為線程池的數量為2,最多開兩個線程,且這里是time.sleep(3),延遲操作,所以會兩個線程

同時執行,實際上是遇到sleep阻塞之后就執行線程2了,所以兩個線程執行了大概3秒!如果涉及計算密集型,

多線程是沒用的,因為python默認一次智能執行一個!join之后再使用apply_async()方法就會報錯,因為這個

時候線程池已經關了,而且這里沒有start()方法可以調用再次開啟...

內置進程池:

 1 from multiprocessing import Pool  # 進程池
 2 import time
 3 w_start = time.time()
 4 def worker(kill=0):
 5     time.sleep(3)
 6     print('子進程正在執行{}'.format(kill))
 7 pool = Pool(4)  # 參數是進程池的數量,不寫默認是1個進程
 8 for i in range(5):
 9     pool.apply_async(worker)
10 pool.map_async(worker, [1, 2, 3])  # 把任務給進程池,加async之后,就不會等待運行結束
11 pool.close()  # 關閉線程池 不再提交任務
12 pool.join()  # 等待線程池里面的任務執行完畢
13 print(time.time() - w_start)
14 print('任務執行結束')
15 ###########運行結果:###########
16 子進程正在執行0
17 子進程正在執行0
18 子進程正在執行0
19 子進程正在執行0
20 子進程正在執行0
21 子進程正在執行1
22 子進程正在執行2
23 子進程正在執行3
24 6.215780258178711
25 任務執行結束

  注意到這里的方法都有兩種如:map()------->map_async()

前者會阻塞,加async就不會阻塞。apply()和apply_async()是同樣的。

用線程池(或者進程池)實現並發服務器:

 1 from multiprocessing.pool import ThreadPool
 2 import socket
 3 
 4 server = socket.socket()
 5 server.bind(('', 12345))
 6 server.listen(6)
 7 print('--------等待客戶端連接------')
 8 def worker(conn):
 9     while True:
10         recv_data = conn.recv(1024)
11         if recv_data:
12             print(recv_data)
13             conn.send(recv_data)
14         else:
15             conn.close()
16             break
17 if __name__ == '__main__':
18     pool = ThreadPool(3)
19     while True:
20         conn, address = server.accept()
21         pool.apply_async(worker, args=(conn,))

  由於進程池和線程池API接口設置的都一樣,所以用進程池可以將ThreadPool改成Pool,導包的時候也要修改。

其他代碼都差不多。ThreadPool()默認開啟1個線程(線程池只有一個),這是我電腦的結果,但是老師運行調試的是

cpu的核數!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM