繼承式多執行緒

2022-05-27 03:33:12 字數 4461 閱讀 1862

之前,我們只是簡單的介紹了多執行緒演示,也通過時間設定看出來了,多執行緒和單執行緒的不同。現在我們進行更深入的了解,來聊一聊,另外一種多執行緒方式,繼承式多執行緒,和乙個多執行緒的等待。

說明:繼承式多執行緒是自己自定義類,去繼承theading.tread這個類,通過啟動,去執行run方法中的**。

import threading

import time

class mythead(threading.thread): #繼承threading.thread

"繼承式多執行緒"

def __init__(self,n):

super(mythead,self).__init__()

self.n = n

def 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個執行緒,該如何起吶?這邊我們可以啟動執行緒的時候,把它加到迴圈裡面去。並且來計算一下它的時間。

說明:我們這邊為了方便實驗,就啟動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-".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 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()

注:t1.join() => 等待第乙個執行緒的執行結果,這個結果在沒有返回之前,程式是不往下走的。

t2.start() => 這個後面沒有寫 join() 這個方法,但是程式在退出之前,它肯定要確保執行緒都執行完畢,所以它就預設就有乙個join。所以最後不寫。

說明:上面雖然有我想要的結果,卻失去了並行的效果。我想要的是執行緒依然是並行效果,但是只不過,所有的執行緒統一之後再等主線程往下走。

import threading,time

class mythead(threading.thread):

"繼承式多執行緒"

def __init__(self,n,sleep_time): #增加時間屬性

super(mythead,self).__init__()

self.n = n

self.sleep_time = sleep_time

def 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()

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()。上面**不理解如圖:

說明:我們用上面的執行重新改進一下第二知識點裡面的**,來計算一下10個執行緒啟動執行的時間。

import threading,time

def 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-".format(i),))

t.start()

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

這樣結果正是我們想要的。

多執行緒簡介01 函式式和繼承式實現多執行緒及互斥鎖

多執行緒 cpu 程式 指令集合 程序 程式的執行過程 執行緒 指令執行的最小單位 執行緒安全 慢 同步 非執行緒安全 執行緒不安全 快 非同步 鎖?執行緒鎖 互斥鎖 lock lock.acquire lock.release 繼承方式實現多執行緒 執行緒的狀態 生命週期 建立狀態 就緒狀態 執行...

多執行緒 繼承QObject

這種多執行緒實現方法為 自定義類繼承qobject,寫乙個槽函式作為多執行緒的執行內容 include 多執行緒 include 不是必須的,include view 自定義的類 實現邏輯 定義乙個多執行緒的物件,其作用類似於乙個容器,qthread thread thread.start 啟動多執...

多執行緒03 繼承Thread類

自定義執行緒類繼承thread類 重寫run 方法,編寫執行緒執行體 建立執行緒物件,呼叫start 方法啟動執行緒 package com.faq.demo01 建立執行緒方式一 繼承thread類,重寫run 方法,呼叫start開啟執行緒 總結 注意,執行緒的開啟不一定立即執行,由cpu排程執...