Python多執行緒原理與用法例項剖析

2022-10-04 18:12:07 字數 3514 閱讀 4584

先來看個栗子:

下面來看一下i/o秘籍型的執行緒,舉個栗子——爬蟲,下面是爬下來的用4個執行緒去寫檔案

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import re

import urllib

import threading

import queue

import timeit

def gethtml(url):

html_page = urllib.urlopen(url).read()

return h

# 提取網頁中的url

def geturl(html):

pattern = r'src="(http://img.*?)"' # 正規表示式

imgre = re.compile(pattern)

imglist = re.findall(imgre, html) # re.findall(pattern,string) 在string中尋找所有匹配成功的字串,以列表形式返回值

return imglist

class getimg(threading.thread):

def __init__(self, queue, thread_name=0): # 執行緒公用乙個佇列

threading.thread.__init__(self)

self.queue = queue

self.thread_name = thread_name

self.start() # 啟動執行緒

# 使用佇列實現程序間通訊

def run(self):

global count

while (true):

imgurl = self.queue.get() # 呼叫佇列物件的get()方法從隊頭刪除並返回乙個專案

c程式設計客棧ount += 1

if self.queue.empty():

break

self.queue.task_done() # 當使用者執行緒呼叫 task_done() 以表示檢索了該專案、並完成了所有的工作時,那麼未完成的任務的總數就會減少。

imglist =

def main():

global imglist

url = "" # 要爬的網頁位址

html = gethtml(url)

imglist = geturl(html)

def main_1():

global count

threads =

count = 0

queue = queue.queue()

# 將所有任務加入佇列

for img in imglist:

queue.put(img)

# 多執行緒爬去

for i in range(4):

thread = getimg(queue, i)

threads.append(thread)

# 阻塞執行緒,直到執行緒執行完成

for thread in threads:

thread.join()

if __name__ == '__main__':

main()

t = timeit.timer(main_1)

print t.timeit(1)

4個執行緒的執行耗時為:0.421320716723秒

修改一下main_1換成單執行緒的:

def main_1():

global count

threads =

count = 0

queue = queue.queue()

# 將所有任務加入佇列

for img in imglist:

queue.put(img)

# 多執行緒爬去

for i in range(1):

thread = getimg(queue, i)

threads.append(thread)

# 阻塞執行緒,直到執行緒執行完成

for thread in threads:

thread.join()

單執行緒的執行耗時為:1.35626623274秒

再來看乙個:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import threading

import timeit

def countdown(n):

while n > 0:

n -= 1

def task1():

count = 100000000

thread1 = threading.thread(target=countdown, args=(count,))

thread1.start()

thread1.join()

def task2():

count = 100000000

thread1 = threading.thread(target=countdown, args=(count // 2,))

thread2 = threading.thread(target=countdown, args=(count // 2,))

thread1.start()

thread2.start()

thread1.join()

thread2.join()

if __name__ == '__main__':

t1 = timeit.timer(task1)

print "countdown in one thread ", t1.timeit(1)

t2 = timeit.timer(task2)

print "countdown in two thread ", t2.timeit(1)程式設計客棧

task1是單執行緒,task2是雙線程,在我的4核的機器上的執行結果:

countdown in one th程式設計客棧read  3.59939150155

countdown in two thread  9.87704289712

天吶,雙線程比單執行緒計算慢了2倍多,這是為什麼呢,因為countdown是cpu密集型任務(計算嘛)

i/o密集型任務:執行緒做i/o處理的時候會釋放gil,其他執行緒獲得gil,當該執行緒再做i/o操作時,又會釋放gil,如此往復;

cpu密集型任務:在多核多執行緒比單核多執行緒更差,原因是單核多執行緒,每次釋放gil,喚醒的哪個執行緒都能獲取到gil鎖,所以能夠無縫執行(單核多執行緒的本質就是順序執行),但多核程式設計客棧,cpu0釋放gil後,其他cpu上的執行緒都會進行競爭,但gil可能會馬上又被cpu0(cpu0上可能不止乙個執行緒)拿到,導致其他幾個cpu上被喚醒後的執行緒會醒著等待到切換時間後又進入待排程狀態,這樣會造成執行緒顛簸(thrashing),導致效率更低。

Python多執行緒threading用法

python裡面經常會用到多執行緒,即所有的方法在同一時間開始執行,而不是按順序乙個一 個執行。所用到的模組為threading,下面詳解threading用法。這裡只截圖了one 方法,two three與one內容一樣。按下面圖中的執行方式,三個函式是分別在不同時間執行的。定義乙個執行緒池並把要...

多執行緒 多執行緒原理

我們首先要知道什麼是多執行緒,說白了就是多個執行緒,執行緒是什麼呢,其實就是程序執行的途徑,那麼說道這裡我們又引入了乙個新的名字,就是程序,那麼我們來看看什麼是程序,其實我們自己也能看到,啟動電腦的任務管理器,我們就可以看到程序選項,裡面是我們電腦所有的程序,我們會發現有很多的程序.簡單地說就是程序...

Python之多執行緒程式設計1,執行緒的建立與實現

匯入執行緒庫threading import threading 執行緒的建立 thread1 threading.thread target function,args 2,thread1 thread2 threading.thread target function,args 3,thread...