一.多線程技術(shù)
1.主線程:每個(gè)進(jìn)程默認(rèn)都會(huì)有一個(gè)線程,這個(gè)線程我們一般叫他主線程
默認(rèn)情況下,所有的代碼都是在主線程中執(zhí)行
2.子線程
一個(gè)線程中可以有多個(gè)線程,除了主線程以外,其他的線程需要手動(dòng)添加
3.threading是python中的內(nèi)置模塊,用來支持多線程
Thread類的對象就是線程對象,需要線程的時(shí)候,就創(chuàng)建這個(gè)類或者這個(gè)類的子類對象
import threading
import datetime
import time
def download(file):
print("開始下載",datetime.datetime.now())
time.sleep(5)
print(file+"下載結(jié)束:",datetime.datetime.now())
# print("主線程中的代碼")
# #1.在線程中下載兩個(gè)電影
# download("速度與激情")
# download("沉默的羔羊")
print(threading.currentThread())
#2.在兩個(gè)子線程中去下載電影
"""
Thread(target,args)
target:需要在子線程中調(diào)用的函數(shù)的函數(shù)名
args:函數(shù)的實(shí)參
返回值:創(chuàng)建好的線程對象
"""
t1 = threading.Thread(target=download,args=("速度與激情",))
#開始執(zhí)行t1對應(yīng)的線程中的任務(wù)
t1.start()
t2 = threading.Thread(target=download,args=("哆啦A夢",))
#想要在子線程中執(zhí)行任務(wù),必須通過線程對象調(diào)用start方法才行
t2.start()
print("==========")
輸出:
<_MainThread(MainThread, started 5544)>
開始下載 2018-09-13 17:27:55.494570
開始下載 2018-09-13 17:27:55.495571
==========
速度與激情下載結(jié)束: 2018-09-13 17:28:00.494856
哆啦A夢下載結(jié)束: 2018-09-13 17:28:00.495857
二.面向?qū)ο蟮亩嗑€程技術(shù)
1.聲明一個(gè)類,繼承自Thread類
2.重寫run方法,將需要在子線程中執(zhí)行的任務(wù)放到run方法中
3.在需要子線程的位置去創(chuàng)建這個(gè)類的對象,然后用對象調(diào)用start方法
from threading import Thread
import datetime
import time
from random import randint
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())
print("======")
t1 = DownloadThread("水形物語")
t1.start()
print("++++++")
輸出:
水形物語開始下載: 2018-09-13 17:32:06.642935
++++++
水形物語下載結(jié)束: 2018-09-13 17:32:11.643221
3.join的方法的使用
from threading import Thread
import time
from datetime import datetime
from random import randint
#在兩個(gè)子線程中下載兩個(gè)電影,在主線程中統(tǒng)計(jì)兩個(gè)電影下載的總的時(shí)間
#如果希望兩個(gè)線程結(jié)束后才執(zhí)行某個(gè)操作,就用那個(gè)線程調(diào)用join方法
class DownloadThread(Thread):
def __init__(self,file):
super().__init__()
self.file = file
def run(self):
print(self.file+"開始下載:",datetime.now())
time.sleep(randint(5,15))
print(self.file+"下載結(jié)束:",datetime.now())
t1 = DownloadThread("鋼鐵俠")
t2 = DownloadThread("金剛狼")
start = time.time()
tim1 = t1.start()
tim2 = t2.start()
#系統(tǒng)t1和t2中的代碼都結(jié)束后才執(zhí)行下面的代碼
t1.join() #這句代碼在t1的線程結(jié)束后才執(zhí)行
t2.join()
end = time.time()
print(end-start)
輸出:
鋼鐵俠開始下載: 2018-09-13 17:34:31.197203
金剛狼開始下載: 2018-09-13 17:34:31.197203
鋼鐵俠下載結(jié)束: 2018-09-13 17:34:38.197604
金剛狼下載結(jié)束: 2018-09-13 17:34:43.197890
12.001686573028564
4.線程間的數(shù)據(jù)共享
模擬多個(gè)人對同一個(gè)賬號進(jìn)行操作
同步鎖(RLock)和互斥鎖(Lock)
import time
from threading import Thread,Lock,RLock
class Account:
"""賬號類"""
def __init__(self,balance):
#余額
self.balance = balance
#創(chuàng)建鎖對象
self.lock = Lock()
#存錢的過程:讀出原來的余額,確定錢的一系列操作,
# 將原來的余額加上存的數(shù)額,產(chǎn)生最新的余額再保存
def save_money(self,amount):
print("開始存錢")
#加鎖
self.lock.acquire()
#獲取原來的余額
old_amount = self.balance
#模擬時(shí)間消耗
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)前余額為:",self.balance)
#創(chuàng)建賬號
account = Account(1000)
# account.save_money(200)
# account.get_money(100)
"""
當(dāng)多個(gè)線程同時(shí)對一個(gè)數(shù)據(jù)進(jìn)行操作的時(shí)候,可能會(huì)出現(xiàn)數(shù)據(jù)混亂的問題
"""
t1 = Thread(target=account.save_money,args=(200,))
t2 = Thread(target=account.save_money,args=(1300,))
t3 = Thread(target=account.get_money,args=(800,))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
account.show_balance()
輸出:
當(dāng)前余額為: 1000
開始存錢
開始存錢
開始取錢
存錢成功,余額: 1200
存錢成功,余額: 2500
取錢成功,余額: 1700
當(dāng)前余額為: 1700