先來看個栗子:
下面來看一下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...