并發(fā)

一個場景

在界面編程中,我們往往有很多按鈕,當(dāng)按下某個按鈕就觸發(fā)一個事件。

import time
def btnClicked():
    print "handle click event"
    time.sleep(5)
    print "event handled"

btnClicked()
print "another event happend"

當(dāng)btnClicked()完成后(5秒后),才打印出"another event happend",也就是說當(dāng)按鈕按下后,整個界面就被阻塞了,點哪兒都沒有用。

線程

解決方案是開一個線程,把這個按鈕背后的事件放在這個線程里。

import time
def btnClicked():
    print "handle click event"
    time.sleep(5)
    print "event handled"

from threading import Thread
t = Thread(target=btnClicked)
t.start()
print "another event happend"

我們把按鈕觸發(fā)的事件放在一個線程中執(zhí)行,這樣主程序可以保持active狀態(tài)

進(jìn)程

我們也可以開個進(jìn)程,把一些計算任務(wù)扔到新進(jìn)程上去計算

import multiprocessing
p = multiprocessing.Process(target=btnClicked)
p.start()

GIL

python由于GIL的存在,線程的執(zhí)行模型被限制為只能在解釋器中運行一個線程。所以,python線程不適合處理計算密集型任務(wù),而是適合IO密集型的任務(wù)。

記住這句話:進(jìn)程是資源分配的基本單位,線程是資源調(diào)度的基本單位

線程間通信

我們用queue.Queue來實現(xiàn)線程間的通信

from queue import Queue
from threading import Thread

def producer(out_q):
    n = 10
    while n>0:
        print "produce data {}".format(n)
        out_q.put(n)
        n -= 1
def consumer(in_q):
    while True:
        data = in_q.get()
        print "consume data {}".format(data)
        if data == 1:
            break

q = Queue()

t1 = Thread(target=consumer, args=(q,))
t2 = Thread(target=producer, args=(q,))
t1.start()
t2.start()

上面的代碼中,我們有一個生產(chǎn)者一個消費者,生產(chǎn)者生產(chǎn)數(shù)據(jù)并put進(jìn)隊列,而消費者從隊列里面拉出數(shù)據(jù)并處理。這個例子里面只有一個消費者。當(dāng)然我們也可以生成幾個消費者。

線程池

在某些場景中(比如爬蟲),我們有大量的io請求,如果對每個請求都單獨開一個線程,很可能會產(chǎn)生無數(shù)的線程數(shù),從而耗盡系統(tǒng)資源。更好的方法是,我們先初始化好有一定數(shù)量線程對象的線程池,當(dāng)有任務(wù)要處理并且有空余線程時,才在空余線程上跑任務(wù)。

from multiprocessing.dummy import Pool as ThreadPool
import urllib2
pool = ThreadPool(5)
urls = ["https://v2ex.com", "https://www.v2ex.com/?tab=play",
        "https://www.v2ex.com/?tab=jobs","https://www.v2ex.com/?tab=tech",
        "https://www.v2ex.com/?tab=creative","https://www.v2ex.com/?tab=deals",
        "https://www.v2ex.com/?tab=city", "https://www.v2ex.com/?tab=qna"]
result = pool.map(lambda url: urllib2.urlopen(url), urls)
print result
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容