异步非阻塞io详解 - 极悦
专注Java教育14年 全国咨询/投诉热线:444-1124-454
极悦LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 异步非阻塞io详解

异步非阻塞io详解

更新时间:2022-08-26 09:59:34 来源:极悦 浏览841次

Java基础教程中大家会学到I/O的相关知识,那么,异步非阻塞io是什么?极悦小编来为大家解答。

异步和非阻塞 I/O

实时 Web 功能需要每个用户的长期空闲连接。在传统的同步 Web 服务器中,这意味着为每个用户分配一个线程,这可能非常昂贵。

为了最小化并发连接的成本,Tornado 使用单线程事件循环。这意味着所有应用程序代码都应该以异步和非阻塞为目标,因为一次只能激活一个操作。

术语异步和非阻塞密切相关,经常互换使用,但它们并不完全相同。

阻塞

当一个函数在返回之前等待某事发生时会阻塞。一个函数可能会因为多种原因而阻塞:网络 I/O、磁盘 I/O、互斥锁等。事实上,每个函数在运行和使用 CPU 时都会阻塞,至少有一点点阻塞(举一个极端的例子来演示为什么 CPU 阻塞必须像其他类型的阻塞一样受到重视,请考虑密码散列函数,如 bcrypt,其设计使用数百毫秒的 CPU 时间,远远超过典型的网络或磁盘访问)。

一个函数在某些方面可以是阻塞的,而在其他方面可以是非阻塞的。在 Tornado 的上下文中,我们通常在网络 I/O 的上下文中讨论阻塞,尽管所有类型的阻塞都将被最小化。

异步

异步函数在完成之前返回,并且通常会在触发应用程序中的某些未来操作之前在后台发生一些工作(与正常的 同步函数相反,它们会在返回之前完成它们将要做的所有事情)。异步接口有多种风格:

回调参数

返回占位符 ( Future, Promise, Deferred)

交付到队列

回调注册表(例如 POSIX 信号)

无论使用哪种类型的接口, 根据定义,异步函数与其调用者的交互方式不同;没有免费的方法可以以对其调用者透明的方式使同步函数异步(像gevent这样的系统使用轻量级线程来提供与异步系统相当的性能,但它们实际上并没有使事情异步)。

Tornado 中的异步操作通常返回占位符对象 ( Futures),但一些低级组件(例如IOLoop使用回调的组件)除外。Futures通常使用awaitoryield 关键字转换成它们的结果。

例子

这是一个示例同步函数:

from tornado.httpclient import HTTPClient
def synchronous_fetch(url):
    http_client = HTTPClient()
    response = http_client.fetch(url)
    return response.body

这是作为原生协程异步重写的相同函数:

from tornado.httpclient import AsyncHTTPClient
async def asynchronous_fetch(url):
    http_client = AsyncHTTPClient()
    response = await http_client.fetch(url)
    return response.body

或者为了与旧版本的 Python 兼容,请使用以下tornado.gen模块:

from tornado.httpclient import AsyncHTTPClient
from tornado import gen
@gen.coroutine
def async_fetch_gen(url):
    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(url)
    raise gen.Return(response.body)

协程有点神奇,但它们在内部做的事情是这样的:

from tornado.concurrent import Future
def async_fetch_manual(url):
    http_client = AsyncHTTPClient()
    my_future = Future()
    fetch_future = http_client.fetch(url)
    def on_fetch(f):
        my_future.set_result(f.result().body)
    fetch_future.add_done_callback(on_fetch)
    return my_future

请注意,协程Future在 fetch 完成之前返回它。这就是使协程异步的原因。

任何你可以用协程做的事情,你也可以通过传递回调对象来做,但是协程提供了一个重要的简化,它让你以与同步时相同的方式组织你的代码。这对于错误处理尤其重要,因为try/except块的工作方式与您在协程中所期望的一样,而这很难通过回调实现。如果大家对此比较感兴趣,想了解更多相关知识,可以关注一下极悦的Java极悦在线学习,里面的课程内容由浅到深,细致全面,适合没有基础的小伙伴学习,希望对大家能够有所帮助。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>