tornado學習筆記day07-同步與異步

同步

概念

同步就是按部就班的依次執行我們的代碼

進階

但是有些情況我們有一些比較耗時的從操作,比如去別的地方拿點資源,去其他網站請求數據,去訪問數據庫,上傳文件等等,所以這里面優點瑕疵,有小編一一道來
比如這樣

''' 本模塊的功能:<同步異步demo>'''# 這個就相等于一個客戶端的請求
import time# 添加一個耗時的操作
def longIO():print("開始耗時操作")time.sleep(5)print("結束耗時操作")def reqA():print("開始處理reqA")longIO()print("結束處理reqA")# 這個就相等于另一個客戶端的請求
def reqB():print("開始處理reqB")print("結束處理reqB")
def main():# 這就是同步在處理reqA()reqB()while True:'''# 如果你要想寫死循環,你不要直接寫死循環,你得睡一睡# 為什么要睡一睡呢,因為你要是不睡你會發現你的CPU利用率占100%'''time.sleep(0.1)
if __name__ == '__main__':main()

結果

開始處理reqA
開始耗時操作# 這里等待了5秒鐘
結束耗時操作
結束處理reqA
開始處理reqB
結束處理reqB

在請求中添加了一個耗時的操作,導致了我們的同步的效率特別低了,這樣也體現不出我們tornado高效的優點

'''┌─┐       ┌─┐ + +┌──┘ ┴───────┘ ┴──┐++│                 ││       ───       │++ + + +███████───███████ │+│                 │+│       ─┴─       ││                 │└───┐         ┌───┘│         ││         │   + +│         ││         └──────────────┐│                        ││                        ├─┐│                        ┌─┘│                        │└─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +│ ─┤ ─┤       │ ─┤ ─┤└──┴──┘       └──┴──┘  + + + +神獸保佑代碼無BUG!'''

異步

你干一件事情的同事又去干另一件事情

概述

對于耗時的操作,會交給別人(另一個線程)處理,我們繼續向下執行,當別人結束耗時操作后,再將處理結果返回給我們

回調函數實現異步

異步其實我們已經用了,js里面有一個很明顯的異步,就是在我們發ajax的時候,當我們發完ajax就去干別的活去了,后來ajax有響應了我們才搭理他

來來來,代碼演示如下:

'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Created by victor
'''
# 本模塊的功能:<異步演示demo># 這個就相等于一個客戶端的請求
import time
import threading
''' 添加一個耗時的操作''''''
這樣就會有一個問題,這個run()函數的返回值我們接受不到
為了解決這個問題,我們需要寫一個函數,這個函數叫做回調函數
'''
def longIO(callback):def run(cb):print("開始耗時操作")time.sleep(3)print("結束耗時操作")cb("victor is a wonderful man")threading.Thread(target=run,args=(callback,)).start()

這個longio這部分 ,就像ajax一樣都不用我們來寫了

def finish(data):print("開始處理回調函數")print("接受到longIO的數據為:",data)print("結束處理回調函數")def reqA():print("開始處理reqA")longIO(finish)print("結束處理reqA")# 這個就相等于另一個客戶端的請求
def reqB():print("開始處理reqB")time.sleep(1)print("結束處理reqB")
def main():# 這就是同步在處理reqA()reqB()while True:'''# 如果你要想寫死循環,你不要直接寫死循環,你得睡一睡# 為什么要睡一睡呢,因為你要是不睡你會發現你的CPU利用率占100%'''time.sleep(0.1)if __name__ == '__main__':main()

異步只是說tornado能處理多個請求了,你瀏覽器該等還是得等著

協程實現異步

協程還不理解呢,還想實現異步,你就實現就行了

不用管擁護啥了,進程線程你們搞起來都麻煩呢,更別說協程了

版本1

最low的一個初級版本

'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Created by victor
'''
# 本模塊的功能:<># 這個就相等于一個客戶端的請求
import time
import threadinggen = None# 添加一個耗時的操作
def longIO():def run():print("開始耗時操作")time.sleep(3)try:global gengen.send("victor is wonderful!!!")except StopIteration as e:passprint("結束耗時操作")threading.Thread(target=run,).start()
# 這個longio這部分 ,就像ajax一樣都不用我們來寫了
'''
這樣就會有一個問題,這個run()函數的返回值我們接受不到
為了解決這個問題,我們需要寫一個函數,這個函數叫做回調函數
'''def reqA():print("開始處理reqA")res = yield longIO()print("接受到longIO的數據為:",res)# 這里就相當于掛起了print("結束處理reqA")# 這個就相等于另一個客戶端的請求
def reqB():print("開始處理reqB")time.sleep(1)print("結束處理reqB")def main():# 這就是同步在處理global gengen = reqA()    # 生成一個生成器next(gen)   # 執行reqAreqB()while True:'''# 如果你要想寫死循環,你不要直接寫死循環,你得睡一睡# 為什么要睡一睡呢,因為你要是不睡你會發現你的CPU利用率占100%'''time.sleep(0.1)if __name__ == '__main__':main()
版本2
我們有一個問題

版本1中在調用reqA的時候和reqB的調用方式可不一樣的啊
也就數不能將其視為簡單的函數,而是需要作為生成器來用,我們想的時候是當成一個普通函數來對待

現實
global gen
gen = reqA()    # 生成一個生成器
next(gen)   # 執行reqA
理想
reqA()   # 僅僅的簡單的調用

這個時候寄需要我們的裝飾器來登場了

''' 裝飾器還會寫么'''
def genCoroutine(func):# 這個是帶有參數的裝飾器def wapper(*args,**kwargs):# 其實說白了還是那三句話global gengen = func(*args,**kwargs)  # 生成一個生成器next(gen)  # 執行reqAreturn wapper 

然后定義的時候

@genCoroutine
def reqA():print("開始處理reqA")res = yield longIO()print("接受到longIO的數據為:",res)# 這里就相當于掛起了print("結束處理reqA")

然后執行的時候

'''這個就相等于另一個客戶端的請求 '''
def reqB():print("開始處理reqB")time.sleep(1)print("結束處理reqB")def main():# 這就是同步在處理# global gen# gen = reqA()    # 生成一個生成器# next(gen)   # 執行reqAreqA()reqB()while True:'''# 如果你要想寫死循環,你不要直接寫死循環,你得睡一睡# 為什么要睡一睡呢,因為你要是不睡你會發現你的CPU利用率占100%'''time.sleep(0.1)if __name__ == '__main__':main()
版本3

其實版本2中還有一個問題,他存在一個全局的gen變量,說白了就是假裝讓他不再那塊兒

這個是最復雜版本,看看吧

  1. 文檔說明,導入相關模塊
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Created by victor
'''
# 本模塊的功能:<>import time
import threading
  1. 定義裝飾器(最重要的部分,實現異步,高效,并發的原理)
def genCoroutine(func):'''這個好多人就屢不清了'''def wapper(*args, **kwargs):'''這樣的話這個裝飾器就麻煩了,因為我還得要這個全局的gen啊我需要獲得多個生成器'''gen1 = func()  # reqA的生成器gen2 = next(gen1)  # longIO的生成器# 在這里面創建我的線程# 掛起他def run(g):# 這個就是執行longIO去了res = next(g)try:gen1.send(res)  # 返回給reqA數據except StopIteration as e:# 啥都不干passthreading.Thread(target=run, args=(gen2,)).start()return wapper
  1. 最難執行的部分
'''
# 添加一個耗時的操作
# handler獲取數據,(數據庫,其他服務器,循環耗時)
'''
def longIO():'''現在你只需要知道你的耗時的操作是啥,線程的東西你不用管了tornado都幫你弄好了'''print("開始耗時操作")time.sleep(3)print("結束耗時操作")# 結束耗時操作后的返回數據yield "victor is a cool man"
  1. 被裝飾函數定義
@genCoroutine
def reqA():print("開始處理reqA")res = yield longIO()print("接受到longIO的數據為:", res)# 這里就相當于掛起了print("結束處理reqA")
  1. 另一個耗時函數
''' 這個就相等于另一個客戶端的請求'''
def reqB():print("開始處理reqB")time.sleep(1)print("結束處理reqB")
  1. 程序入口函數
def main():reqA()reqB()while True:time.sleep(0.1)if __name__ == '__main__':main()

以后我們不用謝這么復雜的裝飾器了,tornado已經幫我們寫好了,你只要有異步就用裝飾器來裝飾一下就OK,其他的都不需要寫

tornado里面指正不是這么寫代碼,不然要是這樣寫,你們全費了,tornado留下的都是簡單易用的

這玩意不是你理解不理解,你一開始指定是不理解,你多用才能懂里面的原理

這個協程中的異步,其實他本質上不是協程,以為他用了多個線程,因為協程的定義是在一個線程里面玩的,只是來理解tornado實現原理

相似文章

tornado學習筆記day01
tornado學習筆記day02
tornado學習筆記day03
tornado學習筆記day04
tornado學習筆記day05
tornado學習筆記day06
tornado學習筆記day07
tornado學習筆記day08

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455228.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455228.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455228.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關鍵字: on

關鍵字: on 數據庫在通過連接兩張或多張表來返回記錄時&#xff0c;都會生成一張中間的臨時表&#xff0c;然后再將這張臨時表返回給用戶。 在使用left jion時&#xff0c;on和where條件的區別如下&#xff1a; 1、 on條件是在生成臨時表時使用的條件&#xff0c;它不管on中的條…

天融信安全接入客戶端_天融信提示您警惕物聯網設備Ripple20漏洞風險

近日&#xff0c;天融信阿爾法實驗室在JSOF實驗室發布的由Treck公司開發的TCP/IP軟件庫中獲取到一系列0day漏洞。JSOF實驗室發布的這批漏洞共計19個&#xff0c;被JSOF研究人員稱為"Ripple20"。受此軟件庫影響的產品數量估計超過數億&#xff0c;其中包括智能家居設備…

Service-Oriented Architecture,SOA(轉)

http://blog.csdn.net/WOOSHN/article/details/8036910 介紹&#xff1a; IT體系結構已非常成熟&#xff0c;它是一種成功處理典型IT問題的方法。體系結構中一個受到很大重視且相對較新的分支是面向服務的體系結構(SOA)。SOA經常被吹捧為企業用于解決應用程序靈活性和高維護成本…

tornado學習筆記day08-tornado中的異步

概述 應為epoll主要用來解決網絡的并發問題,所以tornado中的異步也是主要體現在網絡的IO異步上,即異步web請求 tornado.httpclient.AsyncHTTPClient tornado提供異步web請求客戶端,可以用來進行異步web請求, 這個客戶端和服務端是相對來說的,當tornado的Handler去其他位置去…

GreenSock (TweenMax) 動畫案例(二)

實現效果 動畫分解 1.燈光閃爍2.文字出現3.水流4.心電圖 知識點 1.AI(可盡情騷擾UI歐巴)2.SVG(了解基本的知識點)3.TweenMax(GreenSock)4.CSS animation 寫在前面 寫過第一篇文章后GreenSock (TweenMax) 動畫案例(一)再回頭看發現代碼太多&#xff0c;根本沒耐心去看完。所以每…

vue 用key拿對象value_利用 WeakMap 對 Vue 新建數組中的對象賦予 :key

需求在 Vue 中&#xff0c;對組件進行循環都需要加入key以便“就地復用”&#xff0c;可是在某些情況下&#xff0c;我們需要新建多個對象&#xff0c;而這些對象不是從后端獲取到的&#xff0c;而是前端生成的&#xff0c;沒有唯一值&#xff0c;且 Vue 目前版本只允許字符串&…

無限輪播圖片的實現原理

無限輪播圖相信是很多開發人員常用的一個功能&#xff0c;這里總結一下常用的兩種方式的實現原理 一、使用UIScrollview實現無限輪播用UIScrollView實現&#xff0c;在scrollView上添加3個UIImageView&#xff0c;分別用來顯示上一張圖片&#xff0c;當前顯示的圖片&#xff0c…

開啟 JM 的 trace 功能

[JM代碼] 開啟 JM 的 trace 功能本帖最后由 firstime 于 2009-6-15 11:16 AM 編輯 城里漢子說過&#xff1a; trace文件對分析碼流結構很有效。我說的是trace文件&#xff0c;不是一步一步跟蹤&#xff0c;就是編解碼同時生成的 trace_enc.txt 這個文件&#xff0c;里面對每個比…

kafka入門介紹(轉載)

Kafka作為一個分布式的流平臺&#xff0c;這到底意味著什么&#xff1f; 我們認為&#xff0c;一個流處理平臺具有三個關鍵能力&#xff1a; 發布和訂閱消息&#xff08;流&#xff09;&#xff0c;在這方面&#xff0c;它類似于一個消息隊列或企業消息系統。 以容錯的方式存儲…

Cmd Markdown 編輯閱讀器

歡迎使用 Cmd Markdown 編輯閱讀器 我們理解您需要更便捷更高效的工具記錄思想&#xff0c;整理筆記、知識&#xff0c;并將其中承載的價值傳播給他人&#xff0c;Cmd Markdown 是我們給出的答案 —— 我們為記錄思想和分享知識提供更專業的工具。 您可以使用 Cmd Markdown&…

關于在smarty中實現省市區三級聯動

剛開始接觸php&#xff0c;&#xff0c;其實對于一些比較深入的東西還不是很了解&#xff0c;就像是這次的省市區聯動&#xff0c;都是用三張表為基礎編碼的&#xff0c;原諒我的無知&#xff0c;謝謝。 接下來就是編碼部分了&#xff1a; <?php require(./smarty/Smarty.c…

Ubuntu GitLab CI Docker ASP.NET Core 2.0 自動化發布和部署(1)

相關博文&#xff1a; Ubuntu 簡單安裝和配置 GitLabUbuntu 簡單安裝 DockerUbuntu Docker 簡單安裝 GitLabUbuntu Docker 安裝和配置 GitLab CI 持續集成服務器版本 Ubuntu 16.04 LTS。 經過上面四篇博文中的相關安裝和配置&#xff0c;我們主要完成了兩個容器的創建和運行&am…

X264學習筆記(1)

X264學習筆記&#xff08;1&#xff09; X264編碼流程 參數的初始化 1.opt&#xff0c;param根據輸入的參數和標準的規定&#xff0c;進行初始化設置。 Opt的說明如下&#xff1a; Opt->hin用于給出讀入的yuv文件的指針地址 Opt->hout給出了輸出的文件的指針地址 Opt->…

python 數字轉化excel行列_Python實現excel的列名稱轉數字、26進制(A-Z)與10進制互相轉換...

Python實現excel的列名稱轉數字、26進制(A-Z)與10進制互相轉換sequence list( map( lambda x: chr( x ), range( ord( A ), ord( Z ) 1 ) ) )##-----字母轉數字(python實現 1-26A-Z, then AA-AZ)def ten2TwentySix(num):L []numnum-1; #實現從1對應Aif num > 25:while Tr…

錯誤提示:'……' is not assignable to Android.app.Activity Manifest XML

1 問題描述&#xff1a; 針對這段代碼&#xff1a; <activity android:name".fragament.fragment_bulter" /> <activity android:name".fragament.fragment_girl" /> <activity android:name".fragament.fragment_user" />…

關于Lambda和匿名內部類

先上代碼&#xff1a; //gcache(f)public <T,R> Function<T,R> cache(Function<T,R> f){final Map<T,R> cachenew HashMap<>();Function<T,R> gt->{if(cache.containsKey(t)){System.out.println("cached t:"t);return cache…

H26L encoder.cfg參數分析

H264 encoder.cfg參數分析 收藏 (1) 文件操作參數:#Files InputFile "silent.yuv" #輸入序列,YUV 4:2:0 StartFrame 0 # 從視頻流的第幾幀開始編碼 FramesToBeEncoded 30 #編碼圖象幀數,指明了除去 B幀后將要被編碼的幀數(應該再實驗一下&#x…

django-ckeditor表情包修改

一、版本 Django1.11django-ckeditor5.2.2 二、關鍵步驟 1.刪除舊的ckeditor靜態文件 所在目錄&#xff1a;項目目錄下的static文件夾下的ckditor文件夾 rm ckeditor -rf 原因&#xff1a;在安裝ckeditor后需要執行collectstatic命令&#xff0c;這個過程中的查找靜態文件會去…

python中最難的是什么_python什么的最難了

學的人很少的,如果你沒有學過編程,建議學c語言.因為python中文資料很少的.你可以先了解一下phthonpython的歷史python的創始人為guido van rossum。1989年圣誕節期間&#xff0c;在阿姆斯特丹&#xff0c;guido為了打發圣誕節的無趣&#xff0c;決心開發一個新的腳本解釋程序&a…

Python3生成腳本實現重置鍵盤鍵位

個人博客點這里 #!/usr/bin/env python # -*- coding:utf-8 -*- # Created by 秋葉夏風# 本模塊的功能:<重置鍵盤鍵位>import sys import ossave_format "bat" # 這個值可以修改&#xff0c;有兩個選項(bat和reg)&#xff0c;可選擇生成bat批處理文件或者re…