日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

异步同步、阻塞非阻塞、异步回调、线程队列和协程

發(fā)布時間:2025/7/14 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步同步、阻塞非阻塞、异步回调、线程队列和协程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  今天學習了異步同步、阻塞非阻塞、異步回調(diào)、線程隊列和協(xié)程

  一、異步同步和阻塞非阻塞

  線程的三種狀態(tài):

    1、就緒

    2、運行

    3、阻塞

  阻塞:遇到了IO操作 ?代碼卡住 ?無法執(zhí)行下一行 ?CPU會切換到其他任務

  非阻塞: 與阻塞相反 代碼正在執(zhí)行(運行狀態(tài)) 或處于就緒狀態(tài)

  阻塞和非阻塞描述的是運行的狀態(tài)

  同步:提交任務必須等待任務完成,才能執(zhí)行下一行

  異步:提交任務不需要等待任務完成,立即執(zhí)行下一行

  指的是一種提交任務的方式

  二、異步回調(diào)

    為什么回調(diào):子進程幫助主進程完成任務 處理任務的結(jié)果應該交還給主進程
    其他方式也可以將數(shù)據(jù)交還給主進程

      1、shutdown ?主進程會等到所有任務完成

      2、result函數(shù) ?會阻塞直到任務完成

    注意:

      回調(diào)函數(shù)什么時候被執(zhí)行?子進程完成時

      誰在執(zhí)行回調(diào)函數(shù)?主進程

    線程的異步回調(diào)

      使用方式都相同 ?唯一的不同是執(zhí)行回調(diào)函數(shù) 是子線程在執(zhí)行

#進程利用回調(diào)完成生產(chǎn)者消費者
from
concurrent.futures import ProcessPoolExecutor import os pool = ProcessPoolExecutor()#爬蟲 從網(wǎng)絡某個地址獲取一個HTML文件 import requests #該模塊用于網(wǎng)絡請求 #生產(chǎn)數(shù)據(jù) def get_data_task(url):print(os.getpid(),'正在生產(chǎn)數(shù)據(jù)!')response = requests.get(url)text = response.content.decode('utf-8')return text#處理數(shù)據(jù) def parser_data(f):print(os.getpid(),'處理數(shù)據(jù)')print('正在解析:長度%s'%len(f.result()))urls = [ 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com' ]if __name__ == '__main__':for url in urls:f = pool.submit(get_data_task,url)f.add_done_callback(parser_data) #回調(diào)函數(shù)是主進程在執(zhí)行#因為子進程是負責獲取數(shù)據(jù)的 然而數(shù)據(jù)怎么處理 子進程并不知道 應該把數(shù)據(jù)還給主進程print('over') #線程利用回調(diào)完成生產(chǎn)者消費者 from concurrent.futures import ThreadPoolExecutor from threading import current_threadpool = ThreadPoolExecutor #爬蟲 從網(wǎng)絡某個地址獲取一個HTML文件 import requests #該模塊用于網(wǎng)絡(HTTP)請求 #生產(chǎn)數(shù)據(jù) def get_data_task(url):print(current_thread(),'正在生產(chǎn)數(shù)據(jù)!')response = requests.get(url)text = response.content.decode('utf-8')return text#處理數(shù)據(jù) def parser_data(f):print(current_thread(),'處理數(shù)據(jù)')print('正在解析:長度%s'%len(f.result()))urls = [ 'http://www.baidu.com', 'http://www,baidu.com', 'http://www.baidu.com', 'http://www.baidu.com' ]if __name__ =='__main__':for url in urls:f = pool.submit(get_data_task,url)f.add_done_callback(parser_data) #因為是子線程在執(zhí)行回調(diào)函數(shù) 所以沒有主次之分 任何子線程都可以對函數(shù)進行回調(diào)print('over')

  三、線程隊列

  

import queue #普通隊列 先進先出 q = queue.Queue() q.put('a') q.put('b') print(q.get()) print(q.get())#堆棧隊列 先進后出 函數(shù)調(diào)用就是進棧 函數(shù)結(jié)束就出棧 遞歸造成棧溢出 q2 = queue.LifoQueue() q2.put('a') q2.put('b') print('q2.get()')#優(yōu)先級隊列 q3 = queue.PriorityQueue() #數(shù)值越小優(yōu)先級越高 優(yōu)先級相同時 比較大小 小的先取 q3.put((-100,'c')) q3.put((1,'a')) q3.put((100,b)) print(q3.get())

  四、協(xié)程

    協(xié)程的目的是在單線程下實現(xiàn)并發(fā)

    單線程下實現(xiàn)并發(fā) 將io阻塞時間用于執(zhí)行計算 可以提高效率 原理:一直使用CPU直到超時

    怎么實現(xiàn)單線程并發(fā)?

    并發(fā) ?指的是 ?看起來像是同時運行 實際是在任務間來回切換 同時需要保存執(zhí)行的狀態(tài)

    任務是一堆代碼 可以用函數(shù)裝起來

    1.如何讓兩個函數(shù)切換執(zhí)行

      yield可以保存函數(shù)的執(zhí)行狀態(tài)

      通過生成器可以實現(xiàn)偽并發(fā)

      并發(fā)不一定提升效率 ?反而會降低效率 當任務全是計算時

    2.如何知道發(fā)生了io?從而切換執(zhí)行

      目前咱們實現(xiàn)不了。。

    第三方模塊 greenlet 可以實現(xiàn)并發(fā) 但是不能檢測io

    第三方模塊 gevent 封裝greenlet 可以實現(xiàn)單線程并發(fā) 并且能夠檢測io操作 自動切換

    

#用yield實現(xiàn)兩個函數(shù)切換執(zhí)行 import time def task():while True:print('task1')time.sleep(4)yield 1def task2():g = task()while True:try:print('task2')next(g)except Exception:print('任務完成')break task2() #使用greenlet模塊實現(xiàn)并發(fā) import greenlet import time def task1():print('task1 1')time.sleep(2)g2.switch()print('task1 2')g2.swith()def task2():print('task2 1')g1.switch()print('task2 2')g1 = greenlet.greenlet(task1) g2 = greenlet.greenlte(task2) g1.switch() #1.實例化greenlet得到一個對象 傳入要執(zhí)行的任務 #2.先讓某個任務執(zhí)行起來 使用對象調(diào)用switch #3.在任務的執(zhí)行過程中 手動調(diào)用switch來切換 #使用gevent模塊實現(xiàn)單線程的并發(fā) from gevent import monkey monkey.patch_all() import gevent import time def eat():print('eat food 1')time.sleep(2)print('eat food 2')def play():print('play 1')time.sleep(1)print('play 2')g1 = gevent.spawn(eat) g2 = gevent.spawn(play) gevent.joinall([g1,g2]) print('')#1.spawn函數(shù)傳入你的任務 #2.調(diào)用join 去開啟任務 #3.檢測io操作需要打mokey補丁 就是一個函數(shù) 在程序最開始的地方調(diào)用它

?

轉(zhuǎn)載于:https://www.cnblogs.com/xiaocaiyang/p/9954077.html

《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的异步同步、阻塞非阻塞、异步回调、线程队列和协程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。