Pyhton多線程

在了解多線程前先給大家介紹下并發和并行:

   并發:多個任務一起執行 在多任務之間快速切換處理 任務數量大于cpu核數

   并行:一個cpu核處理一個任務,多個cpu核同時處理多個任務 任務數量等于或者小于cpu核數 

再介紹下同步和異步 :

  同步:指線程在訪問某一資源時,獲得了資源的返回結果之后才會執行其他操作(先做某件事,再做某件事) 

  異步: 與同步相對,是指線程在訪問某一資源時,無論是否取得返回結果,都進行下一步操作;當有了資源返回結果時 系統自會通知線程

在Python中,使用threading庫來創建多線程

import threading


def func1():
    for i in range(6):
        time.sleep(1)


def func2():
    for i in range(5):
        time.sleep(1)


# 創建線程對象
t2 = threading.Thread(target=func2)  # target = 方法名
t1 = threading.Thread(target=func1, name='線程1')  # 可以設置線程名字
# start 啟動線程活動
# join([time]) 設置主線程會等待time秒后再往下執行,time默認為子線程結束,多個子線程之間設置的值會增加
# isAlive 返回線程是否活動的
# getName() 返回線程名
# setName() 設置線程名

a = time.time()
t2.start()  # 開始執行線程2
t1.start()  # 開始執行線程1
# 讓主線程等待子線程執行完后再繼續往下執行 同步的概念
t2.join()
t1.join()
b = time.time()
c = b - a
print(c)

threading.currentThread()  # 返回當前執行的線程
threading.enumerate()  # 返回正在運行的所有線程(list) 正在運行指:啟動后、結束前,不包括了啟動前和終止后的線程
threading.activeCount()  # 返回正在運行的線程數量

在threading庫中調用start方法后,start方法調用了他內部的run()方法,我們可以通過繼承threading重寫run()方法來批量創建線程,代碼如下

import threading
import requests
import time


# 通過繼承 threading 類來創建線程 重寫run方法  因為start方法調用的就是run 重寫run
class MyClass(threading.Thread):
    def __init__(self, url):
        self.url = url
        super().__init__()  # 如果要傳入參數重寫init方法時,一定要調用父類的init方法

    # 發送requests請求

    def run(self):
        res = requests.get(self.url)
        print('線程{},返回{}'.format(threading.current_thread(), res.status_code))


t1 = time.time()
for i in range(5):
    t = MyClass('https://www.baidu.com')
    t.start()
t.join()
t2 = time.time()
print(t2 - t1)

可以通過直接實例化類來創建線程對象,如果要傳入參數,在重寫init方法時要注意在最后調用父類的init方法,具體原因可以去查看thrreading庫是如何實現的,在init方法中有很多其他的代碼需要執行。

多線程共享全局變量:

在python中是使用單核來處理線程的,也就是并發并非并行,代碼示例如下:

import threading

a = 100


def func1():
    for i in range(100000):
        global a
        a += 1
    print(a)


def func2():
    for i in range(100000):
        global a
        a += 1
    print(a)


t1 = threading.Thread(target=func1)
t2 = threading.Thread(target=func2) 
t1.start()
t2.start()

當執行func1()方法時,獲取全局變量為100,此時暫停切換到func2()方法,獲取全局變量a為100,并進入for循環,當a循環到20000時(舉例),又切換到func1()方法中開始執行for循環,此時在func1()中a的值為100,循環1次后把a的值又更新為101,造成數據不準確。

解決這個問題會用到互斥鎖、同步、隊列,在下一篇會給大家講到

 

posted @ 2020-04-08 00:49  白加黑呀  閱讀(...)  評論(...編輯  收藏
最新chease0ldman老人