在IO操做的過程當中,當前線程被掛起,而其餘須要CPU執行的代碼就沒法被當前線程執行了。
咱們能夠使用多線程或者多進程來併發執行代碼,爲多個用戶服務。
可是,一旦線程數量過多,CPU的時間就花在線程切換上了,真正運行代碼的時間就少了,結果致使性能嚴重降低。
異步IO:當代碼須要執行一個耗時的IO操做時,它只發出IO指令,並不等待IO結果,而後就去執行其餘代碼了。一段時間後,當IO返回結果時,再通知CPU進行處理。
對於大多數IO密集型的應用程序,使用異步IO將大大提高系統的多任務處理能力。html
協程,又稱微線程,纖程。英文名Coroutine。
子程序(函數)調用是經過棧實現的,一個線程就是執行一個子程序。
協程的執行過程當中,在子程序內部可中斷,而後轉而去執行別的子程序,在適當的時候再回來接着執行。
Python對協程的支持是經過生成器實現的。
在生成器中,咱們不但能夠經過for
循環來迭代,還能夠不斷調用next()
函數獲取由yield語句返回的下一個值。可是Python的yield
不但能夠返回一個值,它還能夠接收調用者發出的參數。python
def consumer(): r = '' while True: n = yield r if not n: return print('[CONSUMER] Consuming %s...' % n) r = '200 OK' def produce(c): c.send(None) n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) print('[PRODUCER] Consumer return: %s' % r) c.close() c = consumer() produce(c)
[PRODUCER] Producing 1... [CONSUMER] Consuming 1... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... [CONSUMER] Consuming 2... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... [CONSUMER] Consuming 3... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... [CONSUMER] Consuming 4... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... [CONSUMER] Consuming 5... [PRODUCER] Consumer return: 200 OK
asyncio的編程模型是一個消息循環。咱們從asyncio模塊中直接獲取一個EventLoop的引用,而後把須要執行的協程扔到EventLoop中執行,就實現了異步IO。web
import asyncio @asyncio.coroutine def hello(): print("Hello world!") # 異步調用asyncio.sleep(1): r = yield from asyncio.sleep(1) print("Hello again!") # 獲取EventLoop: loop = asyncio.get_event_loop() # 執行coroutine loop.run_until_complete(hello()) loop.close()
@asyncio.coroutine
把一個生成器標記爲協程類型,而後,咱們就把這個協程扔到EventLoop中執行。編程
import threading import asyncio @asyncio.coroutine def hello(): print('Hello world! (%s)' % threading.currentThread()) yield from asyncio.sleep(1) print('Hello again! (%s)' % threading.currentThread()) loop = asyncio.get_event_loop() tasks = [hello(), hello()] # 封裝兩個協程 loop.run_until_complete(asyncio.wait(tasks)) loop.close() # Hello world! (<_MainThread(MainThread, started 9700)>) # Hello world! (<_MainThread(MainThread, started 9700)>) # Hello again! (<_MainThread(MainThread, started 9700)>) # Hello again! (<_MainThread(MainThread, started 9700)>)
import asyncio async def hello(): print("Hello world!") r = await asyncio.sleep(1) print("Hello again!") # 獲取EventLoop: loop = asyncio.get_event_loop() # 執行coroutine loop.run_until_complete(hello()) loop.close()
import asyncio from aiohttp import web async def index(request): await asyncio.sleep(0.5) return web.Response(body='<h1>Index</h1>'.encode('utf-8'), content_type='text/html') async def hello(request): await asyncio.sleep(0.5) text = '<h1>hello, %s!</h1>' % request.match_info['name'] return web.Response(body=text.encode('utf-8'), content_type='text/html') async def init(loop): app = web.Application(loop=loop) app.router.add_route('GET', '/', index) app.router.add_route('GET', '/hello/{name}', hello) srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000) print('Server started at http://127.0.0.1:8000...') return srv loop = asyncio.get_event_loop() loop.run_until_complete(init(loop)) loop.run_forever()
參考資料:多線程