溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python多線程及其基本使用方法實例分析

發(fā)布時間:2020-10-19 09:12:40 來源:腳本之家 閱讀:221 作者:peersli 欄目:開發(fā)技術(shù)

本文實例講述了Python多線程及其基本使用方法。分享給大家供大家參考,具體如下:

學(xué)習(xí)Python的多線程(Multi-threading),至少應(yīng)該要有進(jìn)程與線程的基本概念,可以參考:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html。

1.Python中的多線程

執(zhí)行一個程序,即在操作系統(tǒng)中開啟了一個進(jìn)程,在某一時刻,一個CPU內(nèi)核只能進(jìn)行一個進(jìn)程的任務(wù),現(xiàn)在的計算機(jī)所說的多進(jìn)程/多任務(wù)其實是通過加快CPU的執(zhí)行速度來實現(xiàn)的,因為一個CPU每秒能執(zhí)行上億次的計算,能夠?qū)M(jìn)程進(jìn)行很多次切換,所以在人為可以感知的時間里,看上去,計算機(jī)確實是在同時執(zhí)行多個程序,即同時處理多個進(jìn)程。
一個進(jìn)程中可以包含有多個線程,這多個線程為實現(xiàn)該進(jìn)程的某個主要功能而運行著,多個線程可以進(jìn)行串行工作,也可以并發(fā)同時進(jìn)行工作,顯然后者可以節(jié)省更多的時間。

在Python中是支持多線程并發(fā)執(zhí)行的,只是Python中的多線程只能利用單核,也就是說Python中的某一個進(jìn)程的多個線程只能在一個CPU核心上運行,而不能分配在多個CPU核心中運行,這是考慮到線程安全的緣故,而Python中的GIL則保證了線程安全。關(guān)于Python中的GIL,可以參考下面一篇文章:《淺析Python的GIL和線程安全》。

下面是自己在學(xué)習(xí)過程中的一些課堂筆記,因為還沒有真正學(xué)習(xí)一些理論,所以可能會有些錯誤,但目前是方便自己的理解:

即GLI是以CPU核心為單位來控制全局鎖,所以是不能跨不同的CPU(核心 )的GLI可以保證同一個進(jìn)程中,某一個線程的共享數(shù)據(jù)在某一時刻只能同時被另外一個線程修改(使用),而不能同時被多個線程修改(使用),如果去掉GLI,則需要自己為線程加鎖,這樣之后,性能比原來還要差。

當(dāng)然,難道就不能充分利用多核CPU或多個CPU了?

做成多進(jìn)程就可以了,不同的進(jìn)程運行在不同的CPU(核心)上,也可以實現(xiàn)并發(fā),只是這樣的話就會比較浪費內(nèi)存空間,考慮同時運行10個QQ程序的情況,假如1個QQ占用500M的內(nèi)存空間,則10個QQ就要占用5G的內(nèi)存空間了。但如果是多線程的話,可能10個QQ還是共享著這500M的內(nèi)存空間。還有一個缺點就是,多進(jìn)程間的數(shù)據(jù)直接訪問可能會比較麻煩,但其實也是可以實現(xiàn)的,比如chrome瀏覽器就是用多進(jìn)程實現(xiàn)的。

目前首先要明確的是,Python中是不能把一個進(jìn)程的多個線程分布在不同的CPU核心上運行的。

2.Python多線程使用方法1

給出下面的程序代碼及注釋:

import threading  #Python多線程模塊
import time
def run(num):
  print 'Hi, I am thread %s..lalala' % num
  time.sleep(1)
for i in range(20):
  t = threading.Thread(target=run, args=(i,))  #多線程使用方法,target為需要執(zhí)行多線程的函數(shù),args為函數(shù)中的參數(shù),注意這里的參數(shù)寫成(i,),即如果只能一個參數(shù),也要加上一個","
  t.start()  #開始執(zhí)行多線程

程序運行結(jié)果如下:

xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ python thread4.py
Hi, I am thread 0..lalala
Hi, I am thread 1..lalala
Hi, I am thread 2..lalala
Hi, I am thread 3..lalala
Hi, I am thread 4..lalala
Hi, I am thread 5..lalala
Hi, I am thread 6..lalala
Hi, I am thread 7..lalala
Hi, I am thread 8..lalala
Hi, I am thread 9..lalala
Hi, I am thread 10..lalala
Hi, I am thread 11..lalala
Hi, I am thread 12..lalala
Hi, I am thread 13..lalala
Hi, I am thread 14..lalala
Hi, I am thread 15..lalala
Hi, I am thread 16..lalala
Hi, I am thread 17..lalala
Hi, I am thread 18..lalala
Hi, I am thread 19..lalala

直接看執(zhí)行結(jié)果是看不出什么的,這里說一下這個程序的執(zhí)行過程:0到19是同時打印輸入的,在打印19后,程序sleep 1秒后才結(jié)束程序的運行。

上面這個程序有20個線程執(zhí)行,每個線程都是:打印字符串+sleep(1)。我們實際看到的結(jié)果是0到19同時打印,然后才sleep 1秒,但是需要注意的是,并非是20個線程才執(zhí)行一次sleep(1),而是在每個線程中都執(zhí)行了一次sleep(1),即該程序?qū)嶋H上是執(zhí)行了20次sleep(1),而我們實際看到的結(jié)果是程序運行時僅僅是暫停了1秒,那是因為這20次sleep(1)是并發(fā)執(zhí)行的。

上面的程序可以這么去理解:20個線程相當(dāng)于有20匹馬,20匹馬同時起跑(打印字符串),然后以同時停1秒(sleep(1)),最后同時到達(dá)終點(20個線程運行結(jié)束,即程序執(zhí)行結(jié)束)。

為了更好的理解上面的程序,可以把上面的代碼改為如下:

import threading
import time
def run(num):
  print 'Hi, I am thread %s..lalala' % num
  time.sleep(1)
for i in range(20):
  t = threading.Thread(target=run, args=(i,))
  t.start()
  t.join()  #等上一個線程執(zhí)行完后再執(zhí)行下一個線程

執(zhí)行結(jié)果如下:

xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ python thread4.py
Hi, I am thread 0..lalala
Hi, I am thread 1..lalala
Hi, I am thread 2..lalala
Hi, I am thread 3..lalala
Hi, I am thread 4..lalala
Hi, I am thread 5..lalala
Hi, I am thread 6..lalala
Hi, I am thread 7..lalala
Hi, I am thread 8..lalala
Hi, I am thread 9..lalala
Hi, I am thread 10..lalala
Hi, I am thread 11..lalala
Hi, I am thread 12..lalala
Hi, I am thread 13..lalala
Hi, I am thread 14..lalala
Hi, I am thread 15..lalala
Hi, I am thread 16..lalala
Hi, I am thread 17..lalala
Hi, I am thread 18..lalala
Hi, I am thread 19..lalala

執(zhí)行結(jié)果看上去跟前面是一樣的,但執(zhí)行過程卻是這樣的:每打印一次字符串,再暫停一秒。

通過這個程序,也就可以更好的理解Python的多線程并發(fā)執(zhí)行了,當(dāng)然,因為這是一個動態(tài)的過程,所以把程序執(zhí)行一遍后會有更好的理解。

3.Python多線程使用方法2

程序代碼如下:

import threading,time
class MyThread(threading.Thread):
  def __init__(self, num):
    threading.Thread.__init__(self)
    self.num = num
  def run(self): #this name must be 'run'
    print 'I am thread %s' % self.num
    time.sleep(2)
for i in range(20):
  t = MyThread(i)
  t.start()

程序的執(zhí)行結(jié)果與方法1是一樣的,這里就不給出了,只是這里利用了面向?qū)ο缶幊痰乃枷敕椒▉碓O(shè)計程序代碼。

更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python進(jìn)程與線程操作技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門與進(jìn)階經(jīng)典教程》、《Python+MySQL數(shù)據(jù)庫程序設(shè)計入門教程》及《Python常見數(shù)據(jù)庫操作技巧匯總》

希望本文所述對大家Python程序設(shè)計有所幫助。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI