欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python基礎(chǔ)教程之多線程編程詳解

 更新時間:2023年06月15日 09:20:04   作者:陸理手記  
Python支持多線程編程和多進程編程,在本教程中,我們將學(xué)習(xí)有關(guān)Python多線程編程的基礎(chǔ)知識、線程同步、線程池以及如何使用多進程,需要的朋友可以參考下

進程(process)指的是正在運行的程序的實例,當我們執(zhí)行某個程序時,進程就被操作系統(tǒng)創(chuàng)建了。而線程(thread)則包含于進程之中,是操作系統(tǒng)能夠進行運算調(diào)度的最小單元,多個線程可以同處一個進程中,且同時處理不同的任務(wù)。一條進程中可以并發(fā)多個線程,而同一條線程將共享該進程中的全部系統(tǒng)資源。

每個進程都有自己獨立的地址空間、內(nèi)存和數(shù)據(jù)棧,因此進程之間通訊不方便,所以需使用用進程間通訊(InterProcess Communication, IPC)。而同一個進程中的線程共享資源,因此線程間通訊非常方便,只需注意數(shù)據(jù)同步與互斥的問題。

1. 多線程基礎(chǔ)

線程是進程內(nèi)的執(zhí)行單元,每個進程都至少有一個線程。Python標準庫提供了thread模塊和threading模塊來支持線程編程。在Python3中,thread模塊已經(jīng)改名為_thread,并在_thread基礎(chǔ)上開發(fā)了更為強大的threading模塊,因此我們可以使用threading.Thread類創(chuàng)建線程對象,并通過start()方法啟動線程。

import threading
def worker():
    print("I am a thread.")
t = threading.Thread(target=worker)
t.start()

在上面的代碼中,我們創(chuàng)建了一個名為worker的函數(shù),它是線程的工作內(nèi)容。我們使用threading.Thread類創(chuàng)建了一個線程對象t,并將worker作為參數(shù)傳遞給了Thread構(gòu)造函數(shù)。然后,我們調(diào)用t.start()方法來啟動線程。當我們運行這段代碼時,會看到以下輸出:

I am a thread.

另外,我們也可以通過繼承Thread類并重寫run方法來實現(xiàn)線程的創(chuàng)建.

import threading
class MyThread(threading.Thread):
	def __init__(self, n):
		self.n = n
		super().__init__() # 調(diào)用父類函數(shù)初始化線程
	def run(self):
		print('線程:', self.n)
for i in range(1,3):
	t = MyThread(i)
	t.start()

果應(yīng)該輸出打印出:

線程1
線程2

2. 多線程同步

當多個線程同時訪問共享資源時,可能會發(fā)生競態(tài)條件。為避免這種情況,我們需要使用線程同步機制。Python提供了鎖(Lock)、信號量(Semaphore)、事件(Event)等機制來實現(xiàn)線程同步。

下面是一個使用鎖來確保線程同步的示例:

import threading
lock = threading.Lock()
count = 0
def worker():
    global count
    lock.acquire()
    try:
        count += 1
    finally:
        lock.release()
threads = []
for i in range(10):
    t = threading.Thread(target=worker)
    threads.append(t)
for t in threads:
    t.start()
for t in threads:
    t.join()
print(count)

在上面的代碼中,我們定義了一個全局變量count和一個鎖對象lock。worker函數(shù)是每個線程的工作內(nèi)容,它通過lock來確保count的修改是原子性的。我們創(chuàng)建了10個線程并啟動它們,等待所有線程執(zhí)行完畢后輸出count的值。當我們運行這段代碼時,會看到以下輸出:

10

如果把鎖去掉后,count的值會是幾呢?動手試試吧!會有意向不到的結(jié)果哦~

3. 線程池

線程池可以用來提高代碼的性能,在需要大量線程處理任務(wù)時,可以使用線程池來減少線程的創(chuàng)建和銷毀次數(shù),提高線程的復(fù)用率。

Python標準庫提供了concurrent.futures模塊來支持線程池編程。我們可以使用ThreadPoolExecutor類來創(chuàng)建和管理線程池。

下面是一個使用線程池來處理任務(wù)的示例:

from concurrent.futures import ThreadPoolExecutor
def worker(num):
    return num * num
executor = ThreadPoolExecutor(max_workers=4)
results = []
for i in range(10):
    result = executor.submit(worker, i)
    results.append(result)
for result in results:
    print(result.result())

在上面的代碼中,我們定義了一個worker函數(shù)用來處理任務(wù)。我們創(chuàng)建了一個ThreadPoolExecutor對象executor,并將最大工作線程數(shù)設(shè)置為4。然后,我們使用submit方法提交10個任務(wù)給executor,并將結(jié)果保存在results列表中。最后,我們遍歷results列表并輸出每個任務(wù)的結(jié)果。

看到這些個熟悉的單詞...恍惚間有種寫java代碼的感覺。

4. 多進程編程

進程是計算機中程序執(zhí)行的基本單位,而線程則是進程中執(zhí)行代碼的單位。多進程編程就是利用多個獨立運行的進程來完成任務(wù)。相比單進程,多進程有以下優(yōu)點:

  • 提高了程序的并發(fā)性能。
  • 可以更好地利用多核CPU。
  • 能夠處理更大的數(shù)據(jù)集。

在進行多進程編程時,需要注意進程之間的通信和同步問題。

5. Python實現(xiàn)多進程編程

Python標準庫中的multiprocessing模塊提供了實現(xiàn)多進程編程的工具。其中常用的方法包括:

  • Process:創(chuàng)建一個新進程。
  • Pool:創(chuàng)建一組進程池。
  • Queue:進程之間的消息隊列。

下面是一個簡單的示例,展示如何使用multiprocessing模塊創(chuàng)建子進程:

import multiprocessing
def worker():
    """子進程要執(zhí)行的任務(wù)"""
    print('子進程正在運行')
if __name__ == '__main__':
    p = multiprocessing.Process(target=worker)
    p.start()
    print('主進程已經(jīng)結(jié)束')

在這個例子中,我們創(chuàng)建一個新的進程,并將其target屬性指向worker函數(shù)。然后使用start方法啟動該進程。注意到在Windows系統(tǒng)中,需要將啟動進程的代碼放在if __name__ == '__main__':語句內(nèi),以避免出現(xiàn)一些問題。

5.1 Python進程池

import multiprocessing
def worker(num):
    """子進程要執(zhí)行的任務(wù)"""
    print(f'子進程{num}正在運行')
if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(worker, range(4))
        print(results)

在這個例子中,我們使用了進程池來管理多個子進程。首先創(chuàng)建一個Pool對象,其中processes參數(shù)指定了進程池的大小。然后使用map方法提交任務(wù),該方法會自動分配任務(wù)給空閑的子進程并返回結(jié)果。最后打印輸出結(jié)果。

5.2 在進程之間進行通信

import multiprocessing
def writer(q):
    """寫入數(shù)據(jù)"""
    for i in range(10):
        q.put(i)
def reader(q):
    """讀取數(shù)據(jù)"""
    while True:
        item = q.get()
        if item is None:
            break
        print(item)
if __name__ == '__main__':
    q = multiprocessing.Queue()
    # 啟動子進程
    p1 = multiprocessing.Process(target=writer, args=(q,))
    p2 = multiprocessing.Process(target=reader, args=(q,))
    p1.start()
    p2.start()
    # 等待子進程結(jié)束
    p1.join()
    q.put(None)
    p2.join()

在這個例子中,我們創(chuàng)建了一個消息隊列,并通過Queue對象將其傳遞給兩個子進程。一個子進程負責(zé)將數(shù)據(jù)寫入隊列中,而另一個子進程則從隊列中讀取數(shù)據(jù)并輸出到屏幕上。注意到在程序末尾我們向隊列中添加了None元素,以便通知讀取數(shù)據(jù)的子進程結(jié)束循環(huán)。

6.多進程計算圓周率

下面是使用Python多進程和蒙特卡羅(Monte Carlo)方法估計圓周率的示例代碼:

import random
from multiprocessing import Pool
def estimate_pi(n):
    num_points_inside_circle = 0
    for _ in range(n):
        x = random.uniform(-1, 1)
        y = random.uniform(-1, 1)
        if x**2 + y**2 <= 1:
            num_points_inside_circle += 1
    return 4 * num_points_inside_circle / n
if __name__ == '__main__':
    num_processes = 4
    num_samples = int(1e8)
    with Pool(num_processes) as p:
        results = p.map(estimate_pi, [int(num_samples/num_processes)] * num_processes)
    print(sum(results)/num_processes)

該代碼使用random模塊中的uniform函數(shù)生成在[−1,1][-1, 1][−1,1]范圍內(nèi)均勻分布的隨機數(shù),并統(tǒng)計落入以原點為圓心,半徑為1的圓中的點數(shù)。最后,將所有子進程的結(jié)果相加并除以進程數(shù)以得到圓周率的估計值。我算出的結(jié)果是3.1416664800000005, 你們呢?

其中,Pool(num_processes) 創(chuàng)建一個具有num_processes個進程的進程池,p.map(estimate_pi, [int(num_samples/num_processes)] * num_processes) 在每個進程上調(diào)用estimate_pi函數(shù),并將輸入?yún)?shù)設(shè)為所需的樣本數(shù)量的四分之一,然后返回其結(jié)果。

7.總結(jié)

在Python多線程與進程編程中,我們不僅要理解和掌握的關(guān)于threading 模塊和multiprocessing模塊如何使用,更要掌握的是線程和進程之間的區(qū)別和聯(lián)系以及線程通信、進程通信的方式。

Python提供了豐富的多線程和多進程編程工具,使我們能夠更有效地利用計算機的多核心處理能力。線程同步和線程池等同步原語可以幫助我們避免競爭條件,并提高程序性能。使用好多線程和多進程,可以使Python編程變得更加高效和靈活。Python爬蟲應(yīng)用中,經(jīng)常會大量使用線程和進程來提升抓取效率哦

以上就是Python基礎(chǔ)教程之多線程編程詳解的詳細內(nèi)容,更多關(guān)于Python多線程編程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python利用tkinter實現(xiàn)屏保

    python利用tkinter實現(xiàn)屏保

    這篇文章主要為大家詳細介紹了python利用tkinter實現(xiàn)屏保,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Python之Django自動實現(xiàn)html代碼(下拉框,數(shù)據(jù)選擇)

    Python之Django自動實現(xiàn)html代碼(下拉框,數(shù)據(jù)選擇)

    這篇文章主要介紹了Python之Django自動實現(xiàn)html代碼(下拉框,數(shù)據(jù)選擇),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Windows下實現(xiàn)pytorch環(huán)境搭建

    Windows下實現(xiàn)pytorch環(huán)境搭建

    這篇文章主要介紹了Windows下實現(xiàn)pytorch環(huán)境搭建,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 基于Python的socket庫實現(xiàn)通信功能的示例代碼

    基于Python的socket庫實現(xiàn)通信功能的示例代碼

    本文主要給大家介紹了如何使用python的socket庫實現(xiàn)通信功能,這里簡單的給每個客戶端增加一個不重復(fù)的uid,客戶端之間可以根據(jù)這個uid選擇進行廣播通信,感興趣的小伙伴快來看看吧
    2023-08-08
  • Python中使用Inotify監(jiān)控文件實例

    Python中使用Inotify監(jiān)控文件實例

    這篇文章主要介紹了Python中使用Inotify監(jiān)控文件實例,本文直接給出實現(xiàn)代碼,需要的朋友可以參考下
    2015-02-02
  • 如何利用Python合并兩張圖片

    如何利用Python合并兩張圖片

    在Python中可以使用PIL庫(Python Imaging Library)來合并兩張圖片,這篇文章主要給大家介紹了關(guān)于如何利用Python合并兩張圖片的相關(guān)資料,文中給了詳細的代碼示例,需要的朋友可以參考下
    2024-03-03
  • Python類的繼承用法示例

    Python類的繼承用法示例

    這篇文章主要介紹了Python類的繼承用法,結(jié)合實例形式分析了Python類的定義、繼承等相關(guān)操作技巧,需要的朋友可以參考下
    2019-01-01
  • Python雙向鏈表插入節(jié)點方式

    Python雙向鏈表插入節(jié)點方式

    這篇文章主要介紹了Python雙向鏈表插入節(jié)點方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Python K-means實現(xiàn)簡單圖像聚類的示例代碼

    Python K-means實現(xiàn)簡單圖像聚類的示例代碼

    本文主要介紹了Python K-means實現(xiàn)簡單圖像聚類的示例代碼,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 在python中使用nohup命令說明

    在python中使用nohup命令說明

    這篇文章主要介紹了在python中使用nohup命令說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04

最新評論