執行緒池是多執行緒的一種處理方式,使用者只需要把需要執行的任務放到執行緒池中,不用關心哪個執行緒執行了任務,執行緒會搶占並執行該任務,當執行緒有空閒的時候,就會去等待佇列裡檢視是否還有排隊等待的任務,如果有,就會佇列中取出任務並繼續執行。如果沒有,執行緒就會進入休眠。
接下來我們會建立乙個執行緒池管理類,建立時只需要指定執行緒數量,執行任務時將任務放入執行緒池中即可。
import threading
import queue
import time
import datetime
這裡需要提醒的一點是,我們在開啟執行緒物件的時候必須要設定守護模式,如果不設定主線程就會一直等待子執行緒結束,如果執行緒池為空,也就是無任務的時候佇列的get會一直阻塞,子執行緒不會結束,那麼程式無法結束。
class
threadpool
:"""
主要是配合佇列來進行實現, 我們定義好乙個佇列物件, 然後將我們的任務物件put到我們的佇列物件中.
任何使用多執行緒, 讓我們的執行緒去get佇列中的物件, 然後各自去執行自己get到的任務,
這樣的話其實也就實現了執行緒池
"""def__init__
(self, n)
:"""
構造乙個指定數量執行緒的執行緒池.
:param n: 執行緒數量
"""self.queue_obj = queue.queue(
)for i in
range
(n):
# 開啟執行緒物件
threading.thread(target=self.worker, daemon=
true
).start(
)def
worker
(self)
:"""
執行緒物件, 寫while true是為了能夠一直去執行任務.
:return: none
put一次計數器+1
task_done一次計數器-1
join根據計數器為準, 如果不為0就阻塞
"""while
true
: func = self.queue_obj.get(
)# 當task_done執行後讓計數器為0了, 那join就不阻塞
# join不阻塞意味著func還沒執行完主線程就結束了.
func(
) self.queue_obj.task_done(
)def
(self, func)
:"""
向佇列中傳入的需要執行的函式物件.
:param func: 函式物件
:return: none
"""self.queue_obj.put(func)
defjoin
(self)
:"""
等待佇列中的內容被取完.
:return: none
"""self.queue_obj.join(
)
測試函式
def
task1()
: time.sleep(2)
print
('task1 over'
)def
task2()
: time.sleep(3)
print
('task2 over'
)
執行緒池的使用
if __name__ ==
'__main__'
: p = threadpool(4)
print
('開始時間為:'
, datetime.datetime.now())
# 如果get傳送阻塞意味著隊列為空, 隊列為空意味著join不阻塞, join不阻塞意味著print('結束時間為:')會執行
# print('結束時間為:')會執行意味著主線程沒事情做了, 主線程沒事情做了意味著主線程結束
# 主線程結束意味著不等待設定了守護的執行緒, 不等待意味著子執行緒會隨著主線程的死亡而死亡(這就是為什麼要設定守護模式的原因)
# 如果沒有設定守護模式, get發生阻塞意味著子執行緒任務執行不完 子執行緒任務執行不完意味著主線程一直要等子執行緒完成.
# 主線程一直要等子執行緒完成任務意味著這個程式一直都結束不了 程式一直都結束不了意味著這個程式有毒.
# 主線程等待子執行緒把任務從佇列中取完.
# 子執行緒把任務拿走, 什麼時候做完也只是時間問題而已, 而且這個時間問題和主線程沒關係.
p.join(
)print
('結束時間為:'
, datetime.datetime.now(
))
以上程式的執行結果如下:
開始時間為: 2020-04
-1019:
11:31.275047
task1 over
task1 over
task2 over
task2 over
task2 over
task2 over
task1 over
task1 over
結束時間為: 2020-04
-1019:
11:36.277253
執行緒池的使用無疑提高了程式的執行效率,而且不會對系統造成較大的開銷,執行緒池的最大執行緒數取決於cpu的核心數量,是有上限的。
以上就是博主今天給大家分享的內容了,希望大家能夠有所收穫,最後祝大家學習進步!
實現乙個執行緒池
一.執行緒最主要的三個同步機制 1.訊號量 2.互斥鎖 3.條件變數 二.對三個同步機制分別實現乙個包裝類 ifdef locker h define locker h include include 訊號量的封裝 class sem sem bool wait bool post private ...
執行緒池(一) 實現乙個簡單的執行緒池
我們知道頻繁的建立 銷毀執行緒是不可取的,為了減少建立和銷毀執行緒的次數,讓每個執行緒可以多次使用,我們就可以使用執行緒池,可以降低資源到的消耗。執行緒池裡面肯定有多個執行緒,那麼我們就簡單的用乙個陣列來儲存執行緒,那我們我們預設裡面有 5 個執行緒。那我們執行緒池裡只有五個執行緒能同時工作,那同時...
執行緒池 如何正確的配置乙個執行緒池
我們在建立自己的執行緒池時,會時常因為不知道給核心執行緒數或者最大執行緒數設定多少為好,其實這個時需要看你的執行緒池的使用場景和伺服器cup的配置,根據這些前置條件,我們再去判斷如何去設定合適的執行緒數,並不是我們想設定多少執行緒數大小就可以設定多少,這樣可能會導致執行緒發揮不到最大的效能,甚至還有...