亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

1. 多線程基礎(chǔ)

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

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

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

I am a thread.

另外,我們也可以通過繼承Thread類并重寫run方法來實(shí)現(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. 多線程同步

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

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

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)

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

10

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

3. 線程池

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

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

下面是一個(gè)使用線程池來處理任務(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())

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

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

4. 多進(jìn)程編程

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

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

在進(jìn)行多進(jìn)程編程時(shí),需要注意進(jìn)程之間的通信和同步問題。

5. Python實(shí)現(xiàn)多進(jìn)程編程

Python標(biāo)準(zhǔn)庫中的multiprocessing模塊提供了實(shí)現(xiàn)多進(jìn)程編程的工具。其中常用的方法包括:

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

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

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

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

5.1 Python進(jìn)程池

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

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

5.2 在進(jìn)程之間進(jìn)行通信

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()
    # 啟動(dòng)子進(jìn)程
    p1 = multiprocessing.Process(target=writer, args=(q,))
    p2 = multiprocessing.Process(target=reader, args=(q,))
    p1.start()
    p2.start()
    # 等待子進(jìn)程結(jié)束
    p1.join()
    q.put(None)
    p2.join()

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

6.多進(jìn)程計(jì)算圓周率

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

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)均勻分布的隨機(jī)數(shù),并統(tǒng)計(jì)落入以原點(diǎn)為圓心,半徑為1的圓中的點(diǎn)數(shù)。最后,將所有子進(jìn)程的結(jié)果相加并除以進(jìn)程數(shù)以得到圓周率的估計(jì)值。我算出的結(jié)果是3.1416664800000005, 你們呢?

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

7.總結(jié)

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

    如何利用Python合并兩張圖片

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

    Python類的繼承用法示例

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

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

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

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

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

    在python中使用nohup命令說明

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

最新評(píng)論