01-多線程技術(shù)
1.主線程
每個進程默認都會有一個線程,這個線程我們一般叫作主線程
默認情況下,我們所有的代碼都在主線程中執(zhí)行的
2.子線程
一個進程可以有多個線程骗露,除了主線程以外掠拳,其它的線程需要手動添加
3.threading是Python中的一個內(nèi)置模塊,用來支持多線程
a.Thread類
Thread類的對象就是線程對象噪裕,需要線程的時候,就創(chuàng)建這個類或者這個類的子類對象
b.threading.currentThread()---》用來獲取當(dāng)前線程對象
import threading
import datetime
import time
# 下載兩個電影
def download(file):
print(file + '開始下載:', datetime.datetime.now())
# 讓線程阻塞10秒
time.sleep(10)
print(file+'下載結(jié)束', datetime.datetime.now())
if __name__ == '__main__':
# threading.Thread
print('主線程中的代碼')
print(threading.currentThread())
# 1.在主線程中下載兩個電影:用時20s
# download('西虹市首富')
download('沉默的羔羊')
# 2.在子線程中下載兩個電影:用時10s
'''
Tread(target,args)
target:需要在子線程中調(diào)用的函數(shù)的函數(shù)名
args:函數(shù)的實參
返回值:創(chuàng)建好的線程對象
'''
t1 = threading.Thread(target= download,args=('西虹市首富',))
# 開始執(zhí)行t1對應(yīng)的線程任務(wù)
t1.start()
# t2 = threading.Thread(target= download,args=('沉默的羔羊',))
# # 想要在子線程中執(zhí)行任務(wù)宋渔,必須通過線程對象調(diào)用start方法才行
# t2.start()
print('==========')
02-面向?qū)ο蟮亩嗑€程技術(shù)
1.聲明一個類繼承自Thread類
2.將需要在子線程中執(zhí)行的任務(wù)放到run方法中
3.在需要子線程的位置去創(chuàng)建這個類的對象州疾,然后用對象調(diào)用start方法去執(zhí)行run中的任務(wù)
from threading import Thread
import datetime
import time
from random import randint
注意:繼承的時候可以繼承自己寫的類,也可以繼承別人寫的類或者系統(tǒng)寫的類
class DownloadThread(Thread):
'''下載線程類'''
def __init__(self,file):
super().__init__()
self.file = file
def run(self):
print(self.file + '開始下載:',datetime.datetime.now())
time.sleep(randint(5,10))
print(self.file + '下載結(jié)束:',datetime.datetime.now())
if __name__ == '__main__':
print('==========')
t1 = DownloadThread('西虹市首富')
t1.start()
t2 = DownloadThread('黑客帝國')
t2.start()
print('+-+-+-+-+-')
03-join方法的使用
如果希望某個線程結(jié)束后才進行的操作皇拣,就用那個線程調(diào)用join函數(shù)
from threading import Thread
from random import randint
import time
import datetime
class DownloadThread(Thread):
def __init__(self,file):
super().__init__()
self.file = file
def run(self):
print(self.file+'開始下載',datetime.datetime.now())
time.sleep(randint(5,15))
print(self.file+'下載結(jié)束',datetime.datetime.now())
if __name__ == '__main__':
t1 = DownloadThread('美麗人生')
t2 = DownloadThread('怦然心動')
start = time.time()
tim1 = t1.start()
tim2 = t2.start()
# 在兩個子線程中下載兩個電影严蓖,在主線程中統(tǒng)計兩個電影下載的總時間
# 系統(tǒng)t1和t2中的代碼結(jié)束后才執(zhí)行下面的代碼
t1.join() # 這句代碼后面的代碼在t1對應(yīng)的線程結(jié)束后才執(zhí)行
t2.join()
end = time.time()
print(end-start)
04-線程間的數(shù)據(jù)共享
同步鎖(RLock)和互斥鎖(Lock)
模擬多個人對同一個賬號進行操作
import time
from threading import Thread,Lock
class Account:
'''賬號類'''
def __init__(self,balance):
# 余額
self.balance = balance
# 創(chuàng)建鎖的對象
self.lock = Lock()
# 存錢過程:讀出原來的余額,確定錢的一系列操作氧急,將原來的余額加上存的錢颗胡,產(chǎn)生新的余額,再保存
def save_money(self,amount):
'''存錢'''
print('開始存錢')
加鎖
self.lock.acquire()
# 獲取原來的余額
old_amount = self.balance
# 模擬時間消耗
time.sleep(5)
# 修改余額
self.balance = old_amount + amount
print('存錢成功吩坝,余額是:',self.balance)
解鎖
self.lock.release()
def get_money(self,amount):
'''取錢'''
print('開始取錢')
加鎖
self.lock.acquire()
# 獲取原來的余額
old_amount = self.balance
if old_amount < amount:
print('余額不足')
return
time.sleep(5)
self.balance = old_amount - amount
print('取錢成功,余額是:',self.balance)
解鎖
self.lock.release()
def show_balance(self):
print('當(dāng)前余額:%d'% self.balance)
if __name__ == '__main__':
# 創(chuàng)建賬號
account = Account(1000)
# account.save_money(200)
# account.save_money(100)
# account.show_balance()
當(dāng)多個線程對一個數(shù)據(jù)進行操作時毒姨,可能會出現(xiàn)數(shù)據(jù)混亂的問題
t1 = Thread(target= account.save_money,args= (200,))
t2 = Thread(target=account.save_money, args=(300,))
t1.start()
t2.start()