日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

123 Python程序中的線程操作-協(xié)程

系統(tǒng) 1790 0

目錄

  • 一、什么是協(xié)程
  • 二、為什么要有協(xié)程
  • 三、協(xié)程的優(yōu)缺點(diǎn)
  • 四、如何實(shí)現(xiàn)協(xié)程
  • 五、Gevent模塊
    • 5.1 模塊的安裝
    • 5.2 用法介紹
    • 5.3 代碼實(shí)例
  • 六、gevent之應(yīng)用

一、什么是協(xié)程

協(xié)程: 就是 單線程 實(shí)現(xiàn)并發(fā)

協(xié)程概念本質(zhì)是程序員抽象出來(lái)的,是人為的控制通過(guò)程序的IO去進(jìn)行切換任務(wù)的執(zhí)行

并發(fā):任務(wù)切換+保存狀態(tài)

二、為什么要有協(xié)程

自己控制切換要比操作系統(tǒng)切換快的多.降低了單個(gè)線程的io堵塞時(shí)間,也就是實(shí)現(xiàn)了單線程下效率最高.

三、協(xié)程的優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):

    自己控制切換要比操作系統(tǒng)切換快的多

  • 缺點(diǎn):

    1. 需要自己要檢測(cè)所有的io,但凡有一個(gè)阻塞整體都跟著阻塞.
    2. 無(wú)法利用多核優(yōu)勢(shì).

四、如何實(shí)現(xiàn)協(xié)程

其實(shí)協(xié)程的本質(zhì)就是在單線程下實(shí)現(xiàn)并發(fā),也就是通過(guò)生成器 yield next 進(jìn)行迭代生成器,實(shí)現(xiàn)切換任務(wù)和保存任務(wù)。

在Python中我們需要使用gevnet模塊來(lái)實(shí)現(xiàn)協(xié)程

五、Gevent模塊

Gevent 是一個(gè)第三方庫(kù),可以輕松通過(guò)gevent實(shí)現(xiàn)并發(fā)同步或異步編程,在gevent中用到的主要模式是Greenlet,它是以C擴(kuò)展模塊形式接入Python的輕量級(jí)協(xié)程。 Greenlet全部運(yùn)行在主程序操作系統(tǒng)進(jìn)程的內(nèi)部,但它們被協(xié)作式地調(diào)度。

5.1 模塊的安裝

安裝: pip3 install gevent

5.2 用法介紹

g1=gevent.spawn(func,1,,2,3,x=4,y=5) :創(chuàng)建一個(gè)協(xié)程對(duì)象g1,spawn括號(hào)內(nèi)第一個(gè)參數(shù)是函數(shù)名,如eat,后面可以有多個(gè)參數(shù),可以是位置實(shí)參或關(guān)鍵字實(shí)參,都是傳給函數(shù)eat的

          
            g2=gevent.spawn(func2)
          
        

g1.join() :等待g1結(jié)束

g2.join() :等待g2結(jié)束

上述兩步合作一步: gevent.joinall([g1,g2])

g1.value :拿到func1的返回值

5.3 代碼實(shí)例

通過(guò) from gevent import monkey;

monkey.patch_all() 去補(bǔ)丁,捕獲所以IO

from gevent import monkey;monkey.patch_all() 必須放到被打補(bǔ)丁者的前面,如time,socket模塊之前。

          
            import time
from gevent import monkey;monkey.patch_all()
'''打了一個(gè)補(bǔ)丁,它可以實(shí)現(xiàn)捕獲非gevent的所有io'''
import gevent

def eat():
    print('eat 1')
    time.sleep(2)
    # gevent.sleep(2)   # 可以這樣單獨(dú)捕捉阻塞,但是太麻煩,所以直接打補(bǔ)丁,捕捉運(yùn)行期間的全部IO
    print('eat 2')
def play():
    print('play 1')
    # 瘋狂的計(jì)算呢沒(méi)有io
    time.sleep(3)
    # gevent.sleep(3)   # 可以這樣單獨(dú)捕捉阻塞,但是太麻煩,所以直接打補(bǔ)丁,捕捉運(yùn)行期間的全部IO
    print('play 2')

'''
gevent實(shí)現(xiàn)協(xié)程的模塊,它可以捕獲單線程中的io并去切換任務(wù)
'''
if __name__ == '__main__':
    # 把本該串行的代碼通過(guò)協(xié)程完成單線程并行
    start = time.time()
    g1 = gevent.spawn(eat)      # 創(chuàng)建一個(gè)協(xié)程對(duì)象
    g2 = gevent.spawn(play)
    # g1.join() # 等待回收協(xié)程對(duì)象
    # g2.join()
    gevent.joinall([g1,g2])     # 把上面兩步并一步
    end = time.time()
    print(end-start)
          
        

六、gevent之應(yīng)用

通過(guò)gevent實(shí)現(xiàn)單線程下的socket并發(fā)

注意: from gevent import monkey;monkey.patch_all()一定要放到導(dǎo)入socket模塊之前,否則gevent無(wú)法識(shí)別socket的阻塞。

服務(wù)器

          
            import socket
from gevent import monkey; monkey.patch_all()   # 打補(bǔ)丁
import gevent

'''
基于協(xié)程的socket通訊

協(xié)程:?jiǎn)尉€程下實(shí)現(xiàn)并發(fā)
'''

def connec_interface(conn,addr):
    while 1:
        try:
            data = conn.recv(1024)
            if not data:
                break
            print(f"來(lái)自{addr}的消息:",data.decode("utf8"))
            data = input(f"與{addr}聊天")
            conn.send(data.encode("utf8"))
        except:
            break


if __name__ == '__main__':
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.bind(("127.0.0.1",8080))
    server.listen(5)

    while 1:
        print("等待連接。。。")
        conn,addr = server.accept()
        print("連接成功")
        gevent.spawn(connec_interface, conn, addr)  # 創(chuàng)建一個(gè)協(xié)程對(duì)象
          
        

客戶(hù)端

          
            import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8080))

while 1:
    msg = input("請(qǐng)輸入內(nèi)容")
    client.send(msg.encode("utf8"))
    data = client.recv(1024)
    if not data:
        break
    print(data.decode("utf8"))
          
        

更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 陈巴尔虎旗| 孟津县| 阳原县| 大同市| 沾益县| 剑河县| 恩平市| 通榆县| 板桥市| 阳江市| 富蕴县| 长垣县| 泌阳县| 松阳县| 五大连池市| 桑植县| 筠连县| 信阳市| 双辽市| 白山市| 凌源市| 永清县| 泾阳县| 昆山市| 台湾省| 兴山县| 安多县| 石台县| 博湖县| 灌南县| 蕲春县| 罗城| 阜康市| 清徐县| 巴林右旗| 恩平市| 平邑县| 邹平县| 广昌县| 临朐县| 招远市|