day9-继承式多线程
一、前言
之前,我們只是簡單的介紹了多線程演示,也通過時間設置看出來了,多線程和單線程的不同。現在我們進行更深入的了解,來聊一聊,另外一種多線程方式,繼承式多線程,和一個多線程的等待。
二、繼承式多線程
2.1、定義
說明:繼承式多線程是自己自定義類,去繼承theading.Tread這個類,通過啟動,去執行run方法中的代碼。
import threading import timeclass MyThead(threading.Thread): #繼承threading.Thread"繼承式多線程"def __init__(self,n):super(MyThead,self).__init__()self.n = ndef run(self): #重寫run方法"這個方法不能叫別的名字,只能叫run方法"print("runinit task",self.n)time.sleep(2)t1 = MyThead("t1") #實例化 t2 = MyThead("t2")t1.start() #啟動一個多線程 t2.start()三、啟動多個線程
我們之前只啟動了一個2個線程,還是用那種古老的方式t1,t2。那我想一下子起10個或者100個線程,該如何起吶?這邊我們可以啟動線程的時候,把它加到循環里面去。并且來計算一下它的時間。
3.1、啟動多個線程
說明:我們這邊為了方便實驗,就啟動5個線程吧,暫時不啟動那么多,并且計算一下時間。那有些同學說了,你為啥不啟動1000個線程或者更多一點的線程。這邊注意了:你的計算機是4核的,它能干的事情,就是4個任務。你啟動的線程越多,就代表著要在這個很多線程之間進行上下文切換。相當于我有一本書,我只看了半頁,因為cpu要確保每個人都能執行。也就是說我一本說我要確保你們每一位同學都能看到,那就相當于每個人執行的時間非常少。我把這本說拿過來,一下子又被第二個人,第三個人拿走了。所以就導致所有的人都慢了,所以說你的線程啟動1000,啟動10000就沒有意義了,導致機器越來越慢,所以要適當設置。下面我們就來看看一下子啟動多個線程的例子,例子如下:
import threading,timedef 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-0 task: t-1 task: t-2 task: t-3 task: t-4 --------all thead has finished cost: 0.00096893310546875 task done t-1 task done t-2 task done t-0 task done t-4 task done t-3大家有沒有從上面的程序發現問題,就是我主線程沒有等其他的子線程執行完畢,就直接往下執行了,這是為什么呢?而且這個計算的時間根本不是我們想要的時間,中間的2秒哪里去了?
答案:一個程序至少有一個線程,那先往下走的,沒有等的就是主線程,主線程啟動了子線程之后,子線程就是獨立的,跟主線程就沒有關系了。主線程和它啟動的子線程是并行關系,這就解釋了為什么我的主線程啟動子線程之后,沒有等子線程,而繼續往下走了。所以我們計算不出來時間,因為程序已經不是串行的了。程序本身就是一個線程,就是主線程。但是我就是想測試總共花了多長時間,咋辦吶?不要著急精彩繼續
四、等待線程執行結果
4.1、join設置等待線程執行結果
說明:通過設置在主線程里去等待子線程的執行結果,有了這個執行結果就完了,我要拿所有子線程的執行結果,如果有子線程的執行結果,我們一切都好辦了。
import threading import timeclass MyThead(threading.Thread):"繼承式多線程"def __init__(self,n):super(MyThead,self).__init__()self.n = ndef 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()注:
4.2、實現并發效果
說明:上面雖然有我想要的結果,卻失去了并行的效果。我想要的是線程依然是并行效果,但是只不過,所有的線程統一之后再等主線程往下走。
import threading,timeclass MyThead(threading.Thread):"繼承式多線程"def __init__(self,n,sleep_time): #增加時間屬性super(MyThead,self).__init__()self.n = nself.sleep_time = sleep_timedef run(self):print("runinit task",self.n)time.sleep(self.sleep_time) #每個線程可以傳入不不同的時間print("task done,",self.n)t1 = MyThead("t1",2) #t1傳入2秒 t2 = MyThead("t2",4) #t2傳入4秒t1.start() t2.start()t1.join() #把t1.join()放在線程啟動之后 print("main thead.....")#執行結果 runinit task t1 runinit task t2 task done, t1 main thead..... task done, t2注意了:t1.join() => 這邊只等t1的結果,然后主線程繼續往下走,因為t2需要等4秒,所以,最后打出來的是t2的執行結果。t1的結果到了,就立刻算結果。這邊只計算了t1的結果,沒有t2的結果。如果想算t2的結果,就 t2.join()。上面代碼不理解如圖:
4.3、計算多個線程的執行時間
說明:我們用上面的執行重新改進一下第二知識點里面的代碼,來計算一下10個線程啟動執行的時間。
import threading,timedef run(n):print("task:",n)time.sleep(2)print("task done",n)start_time = time.time() t_objs = [] #存放子線程實例 for i in range(5):t = threading.Thread(target=run,args=("t-{0}".format(i),))t.start()t_objs.append(t) #為了不阻塞后面線程的啟動,不在這里join,先放到一個列表中for t in t_objs: #循環線程實例列表,等待所有線程執行完畢t.join() print("--------all thead has finished") print("cost:",time.time()-start_time)#輸出 task: t-0 task: t-1 task: t-2 task: t-3 task: t-4 task done t-2 task done t-1 task done t-0 task done t-4 task done t-3 --------all thead has finished cost: 2.003025770187378哈哈,這樣結果正是我們想要的。
轉載于:https://www.cnblogs.com/zhangqigao/articles/7255574.html
總結
以上是生活随笔為你收集整理的day9-继承式多线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【干货】Html与CSS入门学习笔记12
- 下一篇: Socket原理