"""author = Zard"""
import threading
from time import sleep
from datetime import datetime
主線程和子線程
默認情況下怖侦,進程有一個線程缚甩,這個線程叫主線程 -- 主線程是系統(tǒng)自動創(chuàng)建的
默認所有的代碼都是在主線程中執(zhí)行
程序猿通過代碼創(chuàng)建的線程都叫子線程
創(chuàng)建子線程
python中內(nèi)置的threading模塊中提供了和線程操作相關的類和方法
threading模塊中有個Thread類,這個類或者這個的子類的對象就是線程對象明场;
需要子線程的時候就創(chuàng)建Thread類的對象
def download(name):
print(' %s 開始下載:%s ' % (datetime.now(),name))
print(threading.current_thread()) # 查看當前執(zhí)行的線程
sleep(5)
print(' %s 下載結束:%s ' % (datetime.now(),name))
if __name__ == '__main__':
# download('龍貓')
# download('你的名字')
創(chuàng)建線程對象
1)語法
Thread(target=函數(shù),args=實參列表) -- 返回子線程對象
2)說明
target - 必須要賦一個函數(shù)潦俺,這個函數(shù)會在子線程中調(diào)用
args - 賦一個元組沈自,元組中的元素就是調(diào)用target函數(shù)的時候需要傳的參數(shù)
創(chuàng)建2個子線程
t1 = threading.Thread(target=download,args=('龍貓',))
t2 = threading.Thread(target=download,args=('你的名字',))
2.讓子線程開始執(zhí)行
線程對象元媚,start() -- 在子線程中調(diào)用target對應download断盛,并且將args中的值作為實參
t1.start()
t2.start()
程序的結束(進程的結束)
一個進程是否結束疼蛾,看是否這個進程中的每個線程都結束
線程結束:任務執(zhí)行完成肛跌,遇到exit(),發(fā)生異常(只針對發(fā)生的線程)
線程中遇到exit()察郁,線程直接結束
程序出現(xiàn)異常只會影響一個線程
from threading import *
from time import sleep
from datetime import datetime
推薦使用衍慎,類似于面向?qū)ο蟮姆绞?/p>
通過創(chuàng)建Thread類的子類對象來創(chuàng)建 子線程
1)聲明一個類繼承Thread
class DownloadThread(Thread):
def __init__(self,name):
super().__init__()
self.name = name
2)實現(xiàn)run方法,這個方法中的代碼就是會在子線程中執(zhí)行的代碼
def run(self) -> None:
print(' %s 開始下載:%s ' % (datetime.now(),self.name))
print(current_thread()) # 查看當前執(zhí)行的線程
sleep(5)
print(' %s 下載結束:%s ' % (datetime.now(), self.name))
if __name__ == '__main__':
# 3)創(chuàng)建子類的線程對象
t1 = DownloadThread('你是魔鬼嗎皮钠?')
# 4)通過start去執(zhí)行子線程中的任務
t1.start()
t2 = DownloadThread('程序猿猝死案例集錦')
t2.start()
練習:用套接字實現(xiàn)西饵,一個服務器同時處理多個客戶端的功能(一個server可以同時和多個人進行聊天)
from socket import *
from threading import *
# 創(chuàng)建多線程
class Chat(Thread):
def __init__(self,connection,address):
super().__init__()
self.connection = connection
self.address = address
def run(self) -> None:
while True:
re_message = self.connection.recv(1024).decode(encoding='utf-8')
print(self.address,re_message)
message = '你是**嗎?'
self.connection.send(message.encode())
創(chuàng)建服務器對象
server = socket()
# 綁定ip地址
server.bind(('10.7.160.56',8888))
# 開始監(jiān)聽
server.listen(100)
# 服務器不斷運行
print('開始監(jiān)聽...')
while True:
connection,address = server.accept()
print('有新用戶鳞芙!')
t1 = Chat(connection,address)
t1.start()
from threading import *
from datetime import *
from time import *
from random import randint
class Download(Thread):
def __init__(self,name):
super().__init__()
self.name = name
def run(self) -> None:
print('%s - 開始下載 %s'%(datetime.now(),self.name))
t = randint(2,6)
sleep(t)
print('%s - 下載完成 %s'%(datetime.now(),self.name))
if __name__ == '__main__':
print('=========================無憂==========================')
t1 = Download('素人初攝.avi')
t2 = Download('喪心病款.avi')
t3 = Download('夜蒲團子.mp4')
t2.start()
t1.start()
t3.start()
join的使用
線程對象.join()
其他的代碼
這兒的其他的代碼會等到指定的線程對象結束后才會執(zhí)行
t1.join()
t2.join()
t3.join()
from threading import Thread,Lock,RLock
from time import sleep
怎么加鎖
1)保證一個數(shù)據(jù)對應一把鎖:創(chuàng)建鎖對象
2)使用數(shù)據(jù)前加鎖:鎖對象.acquire()
3)保證數(shù)據(jù)使用完成后釋放鎖:鎖對象.release()
數(shù)據(jù)
account = 1000
1.創(chuàng)建鎖對象
lock = Lock()
def save_money(num):
# 2.加鎖
lock.acquire()
print('開始存錢')
global account
balance = account
sleep(4)
account = balance + num
# 3.釋放鎖
lock.release()
print('余額:%d'% account)
def draw_money(num):
print('開始取錢')
# 2.加鎖
lock.acquire()
global account
balance = account
if balance < 0:
print('余額不足')
return
sleep(4)
account = balance - num
print('余額:%d'% account)
# 3.釋放鎖
lock.release()
t1 = Thread(target=save_money,args=(1000,))
t2 = Thread(target=draw_money,args=(500,))
t1.start()
t2.start()