多線程

1.耗時(shí)操作

一個(gè)線程默認(rèn)有一個(gè)線程,這個(gè)線程叫主線程,默認(rèn)情況下所有的任務(wù)(代碼)都是在主線程中執(zhí)行的

import time,datetime

def download(film_name):
    print("開(kāi)始下載%s"%film_name,datetime.datetime.now())
    time.sleep(5)#程序執(zhí)行到這個(gè)地方,線程會(huì)阻塞(停5s),再執(zhí)行后面的代碼
    print("%s下載結(jié)束"%film_name,datetime.datetime.now())

if __name__ == '__main__':
    download("喜洋洋與灰太狼")
    download("花園寶寶")

2.多線程

python中提供了threading模塊
默認(rèn)創(chuàng)建的線程叫主線程,其他的線程叫子線程。如果希望代碼在子線程中執(zhí)行,必須手動(dòng)創(chuàng)建線程對(duì)象。

import threading
import time,datetime

def download(film_name):
    print("開(kāi)始下載%s"%film_name,datetime.datetime.now())
    time.sleep(5)#程序執(zhí)行到這個(gè)地方,線程會(huì)阻塞(停5s),再執(zhí)行后面的代碼
    print("%s下載結(jié)束"%film_name,datetime.datetime.now())
    print(threading.current_thread())


if __name__ == '__main__':

    # 1.創(chuàng)建線程對(duì)象
    """
    Thread - 線程類(lèi)
    Thread(target=函數(shù)名,args=參數(shù)列表) - 直接創(chuàng)建線程對(duì)象 - 返回線程對(duì)象
     函數(shù)名 - 需要在當(dāng)前創(chuàng)建的子線程中執(zhí)行的函數(shù)的函數(shù)變量
     參數(shù)列表 - 元組,元組的元素
     """
    t1 = threading.Thread(target=download,args=("海綿寶寶",))
    t2 = threading.Thread(target=download,args=("花園寶寶",))
    # 2.在子線程中執(zhí)行任務(wù)
    """
    在這兒就是在調(diào)用ti對(duì)應(yīng)的線程中調(diào)用download函數(shù),并且傳遞參數(shù)“海綿寶寶”
    """
    t1.start()
    t2.start()
#打印結(jié)果
"""
開(kāi)始下載海綿寶寶 2018-11-29 19:16:21.574319
開(kāi)始下載花園寶寶 2018-11-29 19:16:21.574319
海綿寶寶下載結(jié)束 花園寶寶下載結(jié)束 2018-11-29 19:16:26.5746052018-11-29 19:16:26.574605
<Thread(Thread-2, started 7488)>

<Thread(Thread-1, started 5160)>
"""

3.線程類(lèi)的子類(lèi)

創(chuàng)建子線程除了直接創(chuàng)建Thread的對(duì)象,還可以創(chuàng)建這個(gè)類(lèi)的子類(lèi)對(duì)象
注意:一個(gè)進(jìn)程中有多個(gè)線程,進(jìn)程會(huì)在所有的線程結(jié)束才會(huì)結(jié)束;
線程中的任務(wù)執(zhí)行完了線程就結(jié)束了

from threading import  Thread,current_thread
#1.聲明一個(gè)類(lèi)繼承Thread
class DownloadThread(Thread):
  def __init__(self,file_name):
      super().__init__()
      self.file_name =file_name
  #2.重寫(xiě)run方法
  def run(self):
      #這個(gè)方法中的代碼會(huì)在子線程當(dāng)中執(zhí)行
      print("開(kāi)始下載:%s"%self.file_name)
      print(current_thread())

# 3.創(chuàng)建線程對(duì)象
d1=DownloadThread("滴滴滴")
d1.start()
d2 =DownloadThread("啊啊啊")
d2.start()
# d1.run()#直接調(diào)用run方法,會(huì)在主線程中執(zhí)行
"""
打印結(jié)果:

開(kāi)始下載:滴滴滴
<DownloadThread(Thread-1, started 6960)>
開(kāi)始下載:啊啊啊
<DownloadThread(Thread-2, started 6432)>
"""

4.join

線程對(duì)象.join() - 等待線程中的任務(wù)執(zhí)行完成

from threading import Thread
import time,datetime,random

class Download(Thread):
    def __init__(self,file_name):
        super().__init__()
        self.file_name=file_name

    def run(self):
        print("開(kāi)始下載%s"%self.file_name)
        a=random.randint(5,12)
        time.sleep(a)
        print("%s下載結(jié)束"%self.file_name,"耗時(shí)%d秒"%a)

if __name__ == '__main__':

    t1 =Download("花園寶寶")
    t2 =Download("海綿寶寶")
    time1 =time.time()
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    time2 =time.time()
    print(time2-time1)

"""
打印結(jié)果:

開(kāi)始下載花園寶寶
開(kāi)始下載海綿寶寶
花園寶寶下載結(jié)束 耗時(shí)10秒
海綿寶寶下載結(jié)束 耗時(shí)11秒
耗時(shí): 11.00162935256958
"""

5.數(shù)據(jù)共享

注意:當(dāng)多個(gè)線程同時(shí)對(duì)同一個(gè)數(shù)據(jù)操作的時(shí)候,可能會(huì)出現(xiàn)數(shù)據(jù)混亂
多個(gè)線程對(duì)一個(gè)數(shù)據(jù)進(jìn)行操作,一個(gè)線程將一個(gè)數(shù)據(jù)讀出來(lái),還沒(méi)來(lái)得及存進(jìn)去,
另一個(gè)線程又去讀了,這個(gè)時(shí)候就可能產(chǎn)生數(shù)據(jù)安全隱患
解決方案:加鎖

Thread - 線程類(lèi)(創(chuàng)建子線程)
Lock - 鎖類(lèi) (創(chuàng)建鎖對(duì)象)

import time,threading
class Account(object):
    def __init__(self,balance,name):
        self.balance=balance
        self.name =name
        self.lock =threading.Lock()#創(chuàng)建鎖對(duì)象
    def save_money(self,num):
        """存錢(qián)"""
        self.lock.acquire()#加鎖

        print("開(kāi)始存錢(qián)")
        old_balance=self.balance
        time.sleep(5)
        self.balance=old_balance+num
        print("存錢(qián)成功")
        self.lock.release()#解鎖
    def pay_money(self,num):
        """取錢(qián)"""
        self.lock.acquire()  # 加鎖
        print("開(kāi)始取錢(qián)")
        old_balance = self.balance
        time.sleep(5)
        self.balance = old_balance - num
        print("取錢(qián)成功")
        self.lock.release()  # 解鎖

a1 =Account(1000,"小明")

#支付寶存錢(qián)
t1 =threading.Thread(target=a1.save_money,args=(1000,))
#銀行卡取錢(qián)
t2 =threading.Thread(target=a1.pay_money,args=(500,))
t1.start()
t2.start()
t1.join()
t2.join()
print("余額:",a1.balance)

"""
打印結(jié)果:

開(kāi)始存錢(qián)
存錢(qián)成功
開(kāi)始取錢(qián)
取錢(qián)成功
余額: 1500
"""

練習(xí):寫(xiě)一個(gè)服務(wù)器,可以不停的和多個(gè)客戶端聊天

server端:
import socket
from threading import Thread
class Receive(Thread):
    def __init__(self,addr,conversation):
        super().__init__()
        self.conversation=conversation
        self.addr = addr
    def run(self):
        while True:
            message = self.conversation.recv(1024).decode("utf-8")
            print(self.addr, ":" + message, sep="")
server =socket.socket()
server.bind(("10.7.187.67",6666))
server.listen(100)
while True:
    conversation,addr=server.accept()
    #給服務(wù)器發(fā)送請(qǐng)求的客戶端連接創(chuàng)建一個(gè)子線程。在子線程中處理每個(gè)請(qǐng)求
    r1 = Receive(addr,conversation)
    r1.start()

client端:

import socket
client=socket.socket()
client.connect(("10.7.187.149",9001))
while True:
    message =input("自己:")
    client.send(message.encode("utf-8"))

練習(xí):下載所有的頭像圖片到本地

import requests
import json
import re
import threading
def download(url:str):
    image_data=requests.get(url).content
    file_name=url.split("/")[-1]
    with open("images/"+file_name,"wb")as f:
        f.write(image_data)

url1 ="https://www.apiopen.top/satinApi?type=1&page=1"
response =requests.get(url1)
json1 =response.json()
data =json1["data"]
for dict1 in data:
    #拿到一個(gè)圖片地址,就為他創(chuàng)建一個(gè)線程對(duì)象,用來(lái)在子線程中下載這種圖片
    t=threading.Thread(target=download,args=(dict1["profile_image"],))
    # t.start()
# print("下載完成")

# with open("files/a.json","w",encoding="utf-8")as f:
#     f.write(json.dumps(json1,ensure_ascii=False))
url1 ="https://www.apiopen.top/satinApi?type=1&page=1"
response =requests.get(url1)
text =response.text
re_str =r'"profile_image":(.+?),'
result =re.findall(re_str,text)
print(result)
# result =re.findall(re_str,json1)
# print(result)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對(duì)應(yīng)一個(gè)進(jìn)程,當(dāng)一個(gè)程序進(jìn)入內(nèi)存運(yùn)行時(shí),即變成一個(gè)進(jìn)程.進(jìn)程是處于運(yùn)行過(guò)程中...
    勝浩_ae28閱讀 5,257評(píng)論 0 23
  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對(duì)應(yīng)一個(gè)進(jìn)程,當(dāng)一個(gè)程序進(jìn)入內(nèi)存運(yùn)行時(shí),即變成一個(gè)進(jìn)程.進(jìn)程是處于運(yùn)行過(guò)程中...
    小徐andorid閱讀 2,993評(píng)論 3 53
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類(lèi) 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,108評(píng)論 1 18
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。在這之前...
    4ea0af17fd67閱讀 634評(píng)論 2 17
  • 不知道大家有沒(méi)有一種經(jīng)歷:你看著一個(gè)人滔滔不絕,或是你看著一份很漂亮的簡(jiǎn)歷,或是你從朋友那里聽(tīng)說(shuō)一個(gè)很厲害的人物時(shí)...
    巖芋閱讀 614評(píng)論 0 0

友情鏈接更多精彩內(nèi)容