【python】-- 繼承式多線程、守護線程

來源:互聯網
上載者:User

標籤:sock   必須   range   執行個體化   五個   設定   highlight   read   退出   

繼承式多線程 1、定義

繼承式多線程是自己自訂類,去繼承theading.Tread這個類,通過類執行個體.start()啟動,去執行run方法中的代碼。

import threadingimport timeclass MyThread(threading.Thread):   # 繼承threading.Thread    """繼承式多線程"""    def __init__(self, n):        threading.Thread.__init__(self)  # 也可以寫成這樣super(MyThread,self).__init__()        self.n = n    def run(self):     # 重寫run方法        """這個方法不能叫別的名字,只能叫run方法"""        print("run", self.n)        time.sleep(2) t1 = MyThread("t1")   # 執行個體化t2 = MyThread("t2") t1.start()   # 啟動一個多線程t2.start()
2、通過for迴圈來啟動線程

 上面的例子只啟動了一個2個線程,還是用那種古老的方式t1,t2。要是一下子起10個或者100個線程,這種方式就不適用了,其實可以在啟動線程的時候,把它加到迴圈裡面去,並且來計算一下它的時間:

這裡設定成啟動5個線程,並且計算一下時間。這裡有個疑問,為什麼不啟動1000個線程或者更多一點的線程?這是因為:電腦是4核的,它能乾的事情,就是4個任務。啟動的線程越多,就代表著要在這個很多線程之間進行環境切換。相當於教室裡有一本書,某個人只看了半頁,因為cpu要確保每個人都能執行,也就是這本是要確保教室每個同學都能看到,那就相當於每個人看書的時間非常少。也就是說某個同學剛剛把這本書拿過來,一下子又被第二個人,第三個人拿走了。所以就導致所有的人都慢了,所以說如果線程啟動1000,啟動10000就沒有意義了,導致機器越來越慢,所以要適當設定

import threading,time def run(n):   #這邊的run方法的名字是自行定義的,跟繼承式多線程不一樣,那個是強制的    print("task:",n)    time.sleep(2)    print("task done",n) start_time = time.time()  #開始時間for i in range(5):   #一次性啟動5個線程    t = threading.Thread(target=run,args=("t-{0}".format(i),))    t.start() print("--------all thead has finished")print("cost:",time.time()-start_time)  #計算總耗時 #執行結果task: t-0task: t-1task: t-2task: t-3task: t-4--------all thead has finishedcost: 0.00096893310546875task done t-1task done t-2task done t-0task done t-4task done t-3

從上面的程式發現,就是我主線程沒有等其他的子線程執行完畢,就直接往下執行了,這是為什麼呢?而且這個計算的時間根本不是我們想要的時間,中間的sleep 2秒哪裡去了?

其實一個程式至少有一個線程,那先往下走的,沒有等的就是主線程,主線程啟動了子線程之後,子線程就是獨立的,跟主線程就沒有關係了。主線程和它啟動的子線程是並行關係,這就解釋了為什麼我的主線程啟動子線程之後,沒有等子線程,而繼續往下走了。所以計算不出來線程總共耗時時間,因為程式已經不是串列的了。程式本身就是一個線程,就是主線程。如果要想測試這五個線程總共花了多長時間,就需要用到線程的內建韓式join()

3、join設定等待線程執行結果

 3.1、通過設定在主線程裡去等待子線程的執行結果,這裡join()相當於wait的意思

import threadingimport time class MyThead(threading.Thread):    "繼承式多線程"    def __init__(self,n):        super(MyThead,self).__init__()        self.n = n     def run(self):        "這個方法不能叫別的名字,只能叫run方法"        print("runinit task",self.n)        time.sleep(2) t1 = MyThead("t1")t2 = MyThead("t2") t1.start()t1.join()   #等待t1線程的執行結果,相當于于其他語言裡面的 t1.wait()t2.start()

註:

  1. t1.join()    等待第一個線程的執行結果,這個結果在沒有返回之前,程式是不往下走的。所以這個程式變成串列的了。
  2. t2.start()   這個後面沒有寫 join() 這個方法,但是程式在退出之前,它肯定要確保線程都執行完畢,所以它就預設就有一個join()。

 

3.2、實現並發效果

上面雖然有想要的結果,卻失去了並行的效果。如果想要的是線程依然是並行效果,就需要更換join()的位置了

流程圖:

 

 代碼:

import threadingimport timeclass MyThread(threading.Thread):   # 繼承threading.Thread    """繼承式多線程"""    def __init__(self, n, sleep_time):  # 增加時間屬性        threading.Thread.__init__(self)  # 也可以寫成這樣super(MyThread,self).__init__()        self.n = n        self.sleep_time = sleep_time    def run(self):     # 重寫run方法        print("run task", self.n)        time.sleep(self.sleep_time)   # 每個線程可以傳入不不同的時間        print("task done,", self.n) t1 = MyThread("t1", 2)   # 執行個體化t2 = MyThread("t2", 4) t1.start()   # 啟動一個多線程t2.start()t1.join()  # 把t1.join()放線上程啟動之後print("main thread.....")#執行結果run task t1run task t2task done, t1main thread.....task done, t2

 

註:t1.join()    這邊只等t1的結果,然後主線程繼續往下走,因為t2需要等4秒,所以,最後打出來的是t2的執行結果。t1的結果到了,就立刻算結果。這邊只計算了t1的結果,沒有t2的結果

 

3.3 、計算多個線程的執行時間

 重新改進一下第二點 “通過for迴圈來啟動線程” 裡面的代碼,來計算一下10個線程啟動執行的時間

import threadingimport timedef run(n):  # 這邊的run方法的名字是自行定義的,跟繼承式多線程不一樣,那個是強制的    print("task:", n)    time.sleep(2)    print("task done", n)start_time = time.time()  # 開始時間t_obj = []  # 存放子線程執行個體for i in range(10):  # 一次性啟動10個線程    t = threading.Thread(target=run, args=("t-{0}".format(i),))    t.start()    t_obj.append(t)   # 為了不阻塞後麵線程的啟動,不在這裡join,先放到一個列表中for t in t_obj:  # 迴圈線程執行個體列表,等待所有線程執行完畢    t.join()  print("--------all thread has finished")print("cost:", time.time() - start_time)  # 計算總耗時# 執行結果task: t-0task: t-1task: t-2task: t-3task: t-4task: t-5task: t-6task: t-7task: t-8task: t-9task done t-2task done t-1task done t-0task done t-3task done t-4task done t-5task done t-6task done t-9task done t-8task done t-7--------all thread has finishedcost: 2.0067291259765625

 這樣主線程沒有等其他的子線程執行完畢,才繼續往下執行,就能測試出10個線程執行的總共耗時。

 

 

守護線程

上面的例子在不加join的時候,主線程和子線程完全是並行的,沒有了依賴關係,主線程執行了,子線程也執行了。但是加了join之後,主線程依賴子線程執行完畢才往下走。

守護進程:

只要主線程執行完畢,它不管子線程有沒有執行完畢。就退出了。現在就可以把所有的子線程變成守護線程。變成守護線程之後,主程式就不會等子線程結束載退出了。說白了,設定一個主人,在設定幾個僕人,這幾個僕人都是為主人服務的。可以幫主人做很多事情,一個主人(主線程)可以有多個僕人(守護線程),服務的前提是,主線程必須存在,如果主線程不存在,則守護進程也沒了。那守護進程是幹嘛的呢?可以管理一些資源,開啟一些檔案,監聽一些連接埠,監聽一些資源,把一些垃圾資源回收,可以幹很多事情,可以隨便定義。

1、守護線程設定

用setDaemon(True)來設定守護線程

import threadingimport timedef run(n):    print("task:", n)    time.sleep(2)    print("task done", n)start_time = time.time()for i in range(5):    t = threading.Thread(target=run,args=("t-{0}".format(i),))    t.setDaemon(True)  # Daemon意思是守護進程,這邊是把當前線程設定為守護線程    t.start()print("--------all thread has finished")print("cost:", time.time() - start_time)#執行結果task: t-0task: t-1task: t-2task: t-3task: t-4--------all thread has finishedcost: 0.0010023117065429688

註:守護進程一定要在start之前設定,start之後就不能設定了,之後設定會報錯,所以必須在start之前設定

 

2、使用情境

比如寫一個socket_server,每一個連結過來,socket_server就會給這個連結分配一個新的線程。如果我手動的把socket_server停掉。那這種情況你必須手動停掉服務,那它就要down了,這種情況下還要等線程結束嗎?就不用等線程結束了,它自己就直接結束了。這樣,是不是就可以把每個socket線程設定一個守護線程,主線程一旦down掉,就全部退出。

3、知識點補充

查看當前線程和統計活動線程個數,用theading.current_thead()查看當前線程;用theading.active_count()來統計當前活動的線程數,線程個數=子線程數+主線程數

import threading,time def run(n):    print("task:",n)    time.sleep(2)    print("task done",n,threading.current_thread()) #查看每個子線程 start_time = time.time()for i in range(5):    t = threading.Thread(target=run,args=("t-{0}".format(i),))    t.start() print("--------all thead has finished",threading.current_thread(),threading.active_count())#查看主線程和當前活動的所有線程數print("cost:",time.time()-start_time) #執行結果task: t-0task: t-1task: t-2task: t-3task: t-4--------all thead has finished <_MainThread(MainThread, started 3840)> 6cost: 0.0019359588623046875task done t-0 <Thread(Thread-1, started 11536)>task done t-3 <Thread(Thread-4, started 10480)>task done t-2 <Thread(Thread-3, started 11008)>task done t-4 <Thread(Thread-5, started 5088)>task done t-1 <Thread(Thread-2, started 2464)>

  

 

【python】-- 繼承式多線程、守護線程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.