1.threading
python內(nèi)置的threading模塊,可以支持多線程
所有的進(jìn)程默認(rèn)都有一個(gè)線程(一般叫這個(gè)線程為主線程)
如果想要在進(jìn)程中添加其他的線程,就創(chuàng)建線程對(duì)象
技術(shù)1
方法1:直接使用threading
import threading
import time
def download(file, time1):
print('開始下載:%s' % file)
time.sleep(time1)
print('%s:下載結(jié)束' % file)
if __name__ == '__main__':
print('123')
# 1.創(chuàng)建線程對(duì)象
"""
target: 需要在子線程中執(zhí)行的函數(shù)
args: 調(diào)用函數(shù)的實(shí)參列表(參數(shù)類型是列表)
返回值: 線程對(duì)象
"""
t1 = threading.Thread(target=download, args=['一出好戲', 5])
# 2.在子線程中執(zhí)行任務(wù)
t1.start()
print('======')
t2 = threading.Thread(target=download, args=['愛情公寓', 6])
t2.start()
print('======')
# download('愛情公寓')
# download('一出好戲')
技術(shù)2
方式2:寫一個(gè)自己的線程類
1.寫一個(gè)類,繼承自Thread類
2.重寫run方法,在里面規(guī)定需要在子線程中執(zhí)行的任務(wù)
3.實(shí)現(xiàn)在子線程中執(zhí)行任務(wù)對(duì)應(yīng)的功能,如果需要參數(shù),通過類的對(duì)象屬性來傳值
from threading import Thread
import requests
import re
# 下載數(shù)據(jù)
class DownloadThread(Thread):
"""下載類"""
def __init__(self, file_path):
super().__init__()
self.file_path = file_path
def run(self):
"""run方法"""
"""
1.寫在這個(gè)方法中的內(nèi)容就是在子線程中執(zhí)行的內(nèi)容
2.這個(gè)方法不用之間調(diào)用
"""
print('開始下載')
response = requests.request('GET', self.file_path)
data = response.content
# 獲取文件后綴
suffix = re.search(r'\.\w+$', self.file_path).group()
# print(suffix, type(suffix))
with open('./abc'+suffix, 'wb') as f:
f.write(data)
print('下載完成。')
if __name__ == '__main__':
print('=====')
t1 = DownloadThread('http://yuting.local/shareX/Git.exe')
# 通過start簡(jiǎn)接調(diào)用run方法,run方法中的任務(wù)在子線程中執(zhí)行
t1.start()
# 直接調(diào)用run方法,run方法中的任務(wù)在當(dāng)前線程中執(zhí)行
# t1.run()
print('!!!!!')
多線程的應(yīng)用
from threading import Thread
import socket
class CoversationThread(Thread):
"""在子線程中處理不同的客戶端會(huì)話"""
"""
python中可以在函數(shù)參數(shù)后面加一個(gè)冒號(hào),來對(duì)參數(shù)的類型進(jìn)行說明
"""
def __init__(self, conversation:socket.socket, address):
super().__init__()
self.conversation = conversation
self.address =address
def run(self):
while True:
# message = input('>>>')
self.conversation.send('你好??!'.encode())
print(self.conversation.recv(1024).decode(encoding='utf-8'))
if __name__ == '__main__':
server = socket.socket()
server.bind(('10.7.181.81', 8080))
server.listen(64)
while True:
conversation, address = server.accept()
c1 = CoversationThread(conversation, address)
while True:
c1.start()
2.join函數(shù)
如果一個(gè)任務(wù)想要在另一個(gè)子線程中的任務(wù)執(zhí)行完成后再執(zhí)行,就在當(dāng)前任務(wù)前用子線程對(duì)象調(diào)用join方法
所以join也會(huì)阻塞線程,阻塞到對(duì)應(yīng)的子線程中任務(wù)執(zhí)行完為止
from threading import Thread,current_thread
import time
from random import randint
class Download(Thread):
def __init__(self, file):
# 這兒父類的inin方法必須調(diào)用,否則當(dāng)前這個(gè)創(chuàng)建的對(duì)象中就沒有新的線程
super().__init__()
self.file = file
def run(self):
print(current_thread())
print('開始下載:%s' % self.file)
time.sleep(randint(3, 6))
print('%s下載結(jié)束' % self.file)
if __name__ == '__main__':
# time.time():獲取當(dāng)前時(shí)間-時(shí)間戳
start_time = time.time()
t1 = Download('最強(qiáng)Z.mp4')
t1.start()
t2 = Download('最強(qiáng).mp4')
t2.start()
print('======')
# 獲取當(dāng)前線程
"""
主線程:MainThread
子線程:Thread-數(shù)字(數(shù)字從1開始)
"""
print(current_thread())
# 如果一個(gè)任務(wù)想要在另一個(gè)子線程中的任務(wù)執(zhí)行完成后再執(zhí)行,就在當(dāng)前任務(wù)前用子線程對(duì)象調(diào)用join方法
# 所以join也會(huì)阻塞線程,阻塞到對(duì)應(yīng)的子線程中任務(wù)執(zhí)行完為止
t1.join()
# t2.join()
end_time = time.time()
print('總共消耗時(shí)間:%.2f' % (end_time-start_time))