多任務
多任務介紹
對于人來說,一邊聽歌,一邊跳舞就是多任務。
對于電腦,簡單的說,同一時間執行多個程序處理數據叫做多任務
多任務理解
單核CPU
單核cpu在處理多任務的時候是根據時間片輪轉的方式進行的,比如執行QQ1us,然后切換微信執行1us,最后是執行釘釘1us,如此循環。因為cpu的切換速度過快,導致我們認為三個軟件是同時執行的
多核cpu
并發:當cpu不能同時執行當前所有任務時,就會循環執行,是假的多任務
并行:當cpu可以同時執行當前所有任務時,是真的多任務
多任務的實現方式
實現多任務有三種方式:
線程
進程
協程
線程
線程介紹
線程是指在一個單獨進程中,對于CPU和內存而言的多個工作單位,所有線程在進程中的資源都是共享的,包括全局數據、執行代碼等。
線程的使用
先介紹三個方法
setDaemon(True): 主線程A中,創建了子線程B,并且在主線程A中調用了B.setDaemon(),這個的意思是,把主線程A設置為守護線程,這時候,要是主線程A執行結束了,就不管子線程B是否完成,一并和主線程A退出.
join(): 主線程A中,創建了子線程B,并且在主線程A中調用了B.join(),那么,主線程A會在調用的地方等待,直到子線程B完成操作后,才可以接著往下執行
enumerate(): 查看線程數量
使用
代碼示例import threading
import datetime
def A():
print('函數A')
print(datetime.datetime.now())
def B():
print('函數B')
print(datetime.datetime.now())
if __name__ == '__main__':
# 指定線程到A()和B()函數里執行
t1 = threading.Thread(target=A)
t2 = threading.Thread(target=B)
# 執行線程
t1.start()
t2.start()
print('--end--')
從輸出結果可以知道,兩個線程是在同一時間一起執行的。不過因為搶占式的特點,最后一條語句print('--end--')有時會在子線程的前面執行。
join()方法的使用
如果我們想讓print('--end--')在最后執行,可以用到join()方法,當子線程結束后,主線程才會結束。
join方法的使用,代碼示例
import threading
import datetime
def A():
print('函數A')
print(datetime.datetime.now())
def B():
print('函數B')
print(datetime.datetime.now())
if __name__ == '__main__':
# 指定線程到A()和B()函數里執行
t1 = threading.Thread(target=A)
t2 = threading.Thread(target=B)
# 執行線程
t1.start()
t2.start()
t1.join()
t2.join()
print('--end--')
setDaemon()方法的使用
如果不想讓主線程等待子線程完成后才結束,可以使用setDaemon
代碼示例import threading
import time
def A():
for i in range(3):
print("A")
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=A)
t1.setDaemon(True) # 要放在線程開始之前
t1.start()
enumerate()的使用,查看線程數量
代碼示例import threading
import datetime
def A():
print('函數A')
print(datetime.datetime.now())
def B():
print('函數B')
print(datetime.datetime.now())
if __name__ == '__main__':
# 創建兩個主線程,指定線程到A()和B()函數里執行
t1 = threading.Thread(target=A)
t2 = threading.Thread(target=B)
# 執行線程
t1.start()
t2.start()
print(threading.enumerate())
print('--end--')
子線程的創建與執行
當我們調用start()方法時,子線程才會被創建,并且執行
繼承Thread類創建線程
我們可以通過修改Thread類的run()方法里的代碼,來完成重寫run()方法
代碼示例import threading
class T(threading.Thread):
def run(self):
self.a()
def a(self):
for i in range(3):
print('a')
if __name__ == '__main__':
t1 = T()
t1.start() # 當調用start()方法時,會主動調用run()方法
當我們調用start()方法時,會主動調用run()方法
多線程共享全局變量
代碼示例import threading
def a():
global num
num += 1
print(f'a:{num}')
def b():
print(f'b:{num}')
if __name__ == '__main__':
num = 10
print(num)
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
t1.start()
t2.start()
print(num)
線程的傳參
當用線程去函數里執行代碼時,我們可以看到函數后邊是沒有括號()的,所以涉及到傳參的時候我們該怎么解決這個問題?
解決方法
我們可以使用args參數進行傳參,參數為元組
當我們想要傳入字典時,可以使用kwargs進行傳入
代碼示例import threading
def a(x):
print(x)
def b(**kwargs):
print(kwargs)
if __name__ == '__main__':
num = 1
# 使用args參數進行傳參
t1 = threading.Thread(target=a, args=(num,))
# 使用kwargs參數進行傳入字典
t2 = threading.Thread(target=b, kwargs={"A": 1})
t1.start()
t2.start()
線程的資源搶占
代碼示例import threading
def a(x):
global num
for i in range(x):
num += 1
print(f'a: {num}')
def b(x):
global num
for i in range(x):
num += 1
print(f'b: {num}')
if __name__ == '__main__':
num = 100
t1 = threading.Thread(target=a, args=(1000000, ))
t2 = threading.Thread(target=b, args=(1000000, ))
t1.start()
t2.start()
print(num)
運行結果
正常的結果應該是2000100,但是因為資源搶占導致數據不正確,使用鎖就可以避免這個問題,下篇博客我會細講怎么解決這個問題。
最后,有喜歡博主寫的內容的伙伴可以點贊收藏加關注哦!
本文地址:https://blog.csdn.net/weixin_44604586/article/details/107091271
如您對本文有疑問或者有任何想說的,請點擊進行留言回復,萬千網友為您解惑!