1. 程式人生 > 實用技巧 >(十)非同步呼叫與回撥機制

(十)非同步呼叫與回撥機制

一、同步呼叫


提交任務有兩種方式:同步呼叫,非同步呼叫。

同步呼叫:提交完任務後,就在原地等待任務執行完畢,拿到結果再執行下一行程式碼,導致程式是序列執行。

例子:今年你們公司開年會,舉辦了一個吃漢堡大賽,然後把計算下大家一共吃了多少個,誰的最多,誰發的年終獎就最多。

# 1,同步呼叫:提交完任務後,就在原地等待任務執行完畢,拿到結果再執行下一行程式碼,導致程式是序列執行。
from concurrent.futures import ThreadPoolExecutor
import time,random

def eat(name):
    print("%s 正在吃。" % name)
    time.sleep(random.randint(
3,5)) # 吃的時間 res = random.randint(7,13) # 吃了幾個 return {"name":name,"res":res} def count(hamburger): name = hamburger["name"] num = hamburger["res"] print("%s 吃了《%s》個。" % (name,num)) if __name__ == '__main__': pool = ThreadPoolExecutor(3) # 參賽人數,用執行緒池 shit1
= pool.submit(eat,"託兒所").result() # 提交任務,等待任務執行完畢,拿到結果 count(shit1) shit2 = pool.submit(eat,"兒童劫").result() count(shit2) shit3 = pool.submit(eat,"瑞萌萌").result() count(shit3) """ 託兒所 正在吃。 託兒所 吃了《8》個。 兒童劫 正在吃。 兒童劫 吃了《12》個。 瑞萌萌 正在吃。 瑞萌萌 吃了《8》個。 """

二、非同步呼叫與回撥函式


非同步呼叫:提交完任務後,不在原地等待任務執行完畢。

回撥函式:可以為程序池或執行緒池內的每個程序或執行緒繫結一個函式,該函式在程序或執行緒的任務執行完畢後自動觸發,並接收任務的返回值當作引數,該函式稱為回撥函式。

# 2,非同步呼叫:提交完任務後,不在原地等待任務執行完畢,
from concurrent.futures import ThreadPoolExecutor
import time,random

def eat(name):
    print("%s 正在吃。" % name)
    time.sleep(random.randint(3,5))     # 吃的時間
    res = random.randint(7,13)          # 吃幾個
    return {"name":name,"res":res}
    # weight({"name":name,"res":res})   # 這樣寫的話,相當於把兩個函式寫到一起了,耦合了,而我們是要解耦合的

def count(hamburger):
    hamburger = hamburger.result()    # 這裡的hamburger拿到的是一個物件
    name = hamburger["name"]
    num = hamburger["res"]
    print("%s 吃了《%s》個." % (name,num))

if __name__ == '__main__':
    pool = ThreadPoolExecutor(3)    # 參賽人數,用執行緒池

    # 回撥函式是在,前面的函式執行完,有返回值了,自動觸發這個功能,把前面的物件直接當引數傳給weight
    pool.submit(eat,"託兒所").add_done_callback(count)     # 前面是物件,後面的是回撥函式
    pool.submit(eat,"兒童劫").add_done_callback(count)
    pool.submit(eat,"瑞萌萌").add_done_callback(count)
    # count拿到的是一個future物件obj,需要用obj.result()拿到結果,也就是 hamburger.result()

"""
託兒所 正在吃。
兒童劫 正在吃。
瑞萌萌 正在吃。
瑞萌萌 吃了《12》個.
託兒所 吃了《12》個.
兒童劫 吃了《11》個.
"""