我們將會看到一些在Python中使用線程的實例和如何避免線程之間的競爭。你應當將下邊的例子運行多次,以便可以注意到線程是不可預測的和線程每次運行出的不同結果。聲明:從這里開始忘掉你聽到過的關于GIL的東西,因為GIL不會影響到我想要展示的東西。
示例1
我們將要請求五個不同的url:
單線程
import timeimport urllib2 def get_responses(): urls = [ 'http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com' ] start = time.time() for url in urls: print url resp = urllib2.urlopen(url) print resp.getcode() print "Elapsed time: %s" % (time.time()-start) get_responses()
輸出是:
http://www.google.com 200http://www.amazon.com 200http://www.ebay.com 200http://www.alibaba.com 200http://www.reddit.com 200Elapsed time: 3.0814409256
解釋:
url順序的被請求 除非cpu從一個url獲得了回應,否則不會去請求下一個url 網絡請求會花費較長的時間,所以cpu在等待網絡請求的返回時間內一直處于閑置狀態。多線程
import urllib2import timefrom threading import Thread class GetUrlThread(Thread): def __init__(self, url): self.url = url super(GetUrlThread, self).__init__() def run(self): resp = urllib2.urlopen(self.url) print self.url, resp.getcode() def get_responses(): urls = [ 'http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com' ] start = time.time() threads = [] for url in urls: t = GetUrlThread(url) threads.append(t) t.start() for t in threads: t.join() print "Elapsed time: %s" % (time.time()-start) get_responses()
輸出:
http://www.reddit.com 200http://www.google.com 200http://www.amazon.com 200http://www.alibaba.com 200http://www.ebay.com 200Elapsed time: 0.689890861511
解釋:
意識到了程序在執行時間上的提升 我們寫了一個多線程程序來減少cpu的等待時間,當我們在等待一個線程內的網絡請求返回時,這時cpu可以切換到其他線程去進行其他線程內的網絡請求。 我們期望一個線程處理一個url,所以實例化線程類的時候我們傳了一個url。 線程運行意味著執行類里的run()方法。 無論如何我們想每個線程必須執行run()。 為每個url創建一個線程并且調用start()方法,這告訴了cpu可以執行線程中的run()方法了。 我們希望所有的線程執行完畢的時候再計算花費的時間,所以調用了join()方法。 join()可以通知主線程等待這個線程結束后,才可以執行下一條指令。 每個線程我們都調用了join()方法,所以我們是在所有線程執行完畢后計算的運行時間。新聞熱點
疑難解答