精华内容
下载资源
问答
  • 所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法,这样你可以省钱。--------------------------------------------------------------------------------------------------------------------举个例子...

    所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法,这样你可以省钱。

    --------------------------------------------------------------------------------------------------------------------

    举个例子 打电话时同步 发消息是异步

    综述版:

    异步通信”是一种很常用的通信方式。异步通信在发送字符时,所发送的字符之间的时间间隔可以是任意的。当然,接收端必须时刻做好接收的准备(如果接收端主机的电源都没有加上,那么发送端发送字符就没有意义,因为接收端根本无法接收)。发送端可以在任意时刻开始发送字符,因此必须在每一个字符的开始和结束的地方加上标志,即加上开始位和停止位,以便使接收端能够正确地将每一个字符接收下来。异步通信的好处是通信设备简单、便宜,但传输效率较低(因为开始位和停止位的开销所占比例较大)。

    异步通信也可以是以帧作为发送的单位。接收端必须随时做好接收帧的准备。这是,帧的首部必须设有一些特殊的比特组合,使得接收端能够找出一帧的开始。这也称为帧定界。帧定界还包含确定帧的结束位置。这有两种方法。一种是在帧的尾部设有某种特殊的比特组合来标志帧的结束。或者在帧首部中设有帧长度的字段。需要注意的是,在异步发送帧时,并不是说发送端对帧中的每一个字符都必须加上开始位和停止位后再发送出去,而是说,发送端可以在任意时间发送一个帧,而帧与帧之间的时间间隔也可以是任意的。在一帧中的所有比特是连续发送的。发送端不需要在发送一帧之前和接收端进行协调(不需要先进行比特同步)。 每个字符开始发送的时间可以是任意的t0 0 1 1 0 1 1 0起始位结束位t每个帧开始发送的时间可以是任意的以字符为单位发送以帧为单位发送帧开始帧结束

    “同步通信”的通信双方必须先建立同步,即双方的时钟要调整到同一个频率。收发双方不停地发送和接收连续的同步比特流。但这时还有两种不同的同步方式。一种是使用全网同步,用一个非常精确的主时钟对全网所有结点上的时钟进行同步。另一种是使用准同步,各结点的时钟之间允许有微小的误差,然后采用其他措施实现同步传输。

    串口进行通信的方式有两种:同步通信方式和异步通信方式。同步通信方式要求通信双方以相同的时钟频率进行,而且准确协调,通过共享一个单个时钟或定时脉冲源保证发送方和接收方的准确同步,效率较高;异步通信方式不要求双方同步,收发方可采用各自的时钟源,双方遵循异步的通信协议,以字符为数据传输单位,发送方传送字符的时间间隔不确定,发送效率比同步传送效率低。

    具体

    专业版:

    串行通信可以分为两种类型:同步通信、异步通信。

    1.异步通信的特点及信息帧格式:

    以起止式异步协议为例,下图显示的是起止式一帧数据的格式:

    20030414_105-b-1.gif

    图1

    起止式异步通信的特点是:一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以“起始位”开始,以“停止位”结束,字符之间没有固定的时间间隔要求。每一个字符的前面都有一位起始位(低电平,逻辑值),字符本身由5-7位数据位组成,接着字符后面是一位校验位(也可以没有校验位),最后是一位或一位半或二位停止位,停止位后面是不定长的空闲位。停止位和空闲位都规定为高电平(逻辑值1),这样就保证起始位开始处一定有一个下跳沿。

    从图中可看出,这种格式是靠起始位和停止位来实现字符的界定或同步的,故称为起止式协议。

    异步通信可以采用正逻辑或负逻辑,正负逻辑的表示如下表所示:逻辑0逻辑1

    正逻辑低电平高电平

    负逻辑高电平低电平

    异步通信的信息格式如下边的表所示

    起始位逻辑01位

    数据位逻辑0或15位、6位、7位、8位

    校验位逻辑0或11位或无

    停止位逻辑11位,1.5位或2位

    空闲位逻辑1任意数量

    注:表中位数的本质含义是信号出现的时间,故可有分数位,如1.5。

    例:传送8位数据45H(0100,0101B),奇校验,1个停止位,则信号线上的波形象图2所示那样:异步通信的速率:若9600bps,每字符8位,1起始,1停止,无奇偶,则实际每字符传送10位,则960字符/秒。

    20030414_105-b-2.gif

    图2

    2.异步通信的接收过程

    接收端以“接收时钟”和“波特率因子”决定一位的时间长度。下面以波特率因子等于16(接收时钟每16个时钟周期,使接收移位寄存器移位一次)、正逻辑为例说明,如图3所示。

    20030414_105-b-3.gif

    图3

    (1)开始通信时,信号线为空闲(逻辑1),当检测到由1到0的跳变时,开始对“接收时钟”计数。

    (2)当计到8个时钟时,对输入信号进行检测,若仍为低电平,则确认这是“起始位”B,而不是干扰信号。

    (3)接收端检测到起始位后,隔16个接收时钟,对输入信号检测一次,把对应的值作为D0位数据。若为逻辑1, 作为数据位1;若为逻辑0,作为数据位0。

    (4)再隔16个接收时钟,对输入信号检测一次,把对应的值作为D1位数据。….,直到全部数据位都输入。

    (5)检测校验位P(如果有的话)。

    (6)接收到规定的数据位个数和校验位后,通信接口电路希望收到停止位S(逻辑1),若此时未收到逻辑1,说明出现了错误,在状态寄存器中置“帧错误”标志。若没有错误,对全部数据位进行奇偶校验,无校验错时,把数据位从移位寄存器中送数据输入寄存器。若校验错,在状态寄存器中置奇偶错标志。

    (7)本幀信息全部接收完,把线路上出现的高电平作为空闲位。

    (8)当信号再次变为低时,开始进入下一幀的检测。

    3、异步通信的发送过程

    发送端以“发送时钟”和“波特率因子”决定一位的时间长度。

    (1)当初始化后,或者没有信息需要发送时,发送端输出逻辑1,即空闲位,空闲位可以有任意数量。

    (2)当需要发送时,发送端首先输出逻辑0,作为起始位。

    (3)接着,发送端首先发送D0位,直到各数据位发送完。

    (4)如果需要的话,发送端输出校验位。

    (5)最后,发送端输出停止位(逻辑1)。

    (6)如果没有信息需要发送时,发送端输出逻辑1,即空闲位,空闲位可以有任意数量。如果还有信息需要发送,转入第(2)步。

    对于以上发送、接收过程应注意以下几点:

    (1)接收端总是在每个字符的头部(即起始位)进行一次重新定位,因此发送端可以在字符之间插入不等长的空闲位,不影响接收端的接收。

    (2)发送端的发送时钟和接收端的接收时钟,其频率允许有一定差异,当频率差异在一定范围内,不会引起接收端检测错位,能够正确接收。并且这种频率差异不会因多个字符的连续接收而造成误差累计(因为每个字符的开始(起始位处)接收方均重新定位)。只有当发送时钟和接收时钟频率差异太大,引起接收端采样错位,才造成接收错误。

    (3)起始位、校验位、停止位、空闲位的信号,由“发送移位寄存器”自动插入。在接收方,“接收移位寄存器”接收到一帧完整信息(起始、数据、校验、停止)后,仅把数据的各位送至“数据输入寄存器”,即CPU从“数据输入寄存器”中读得的信息,只是有效数字,不包含起始位、校验位、停止位信息。

    1、同步通信方式的特点:

    采用同步通信时,将许多字符组成一个信息组,这样,字符可以一个接一个地传输,但是,在每组信息(通常称为帧)的开始要加上同步字符,在没有信息要传输时,要填上空字符,因为同步传输不允许有间隙。在同步传输过程中,一个字符可以对应5~8位。当然,对同一个传输过程,所有字符对应同样的数位,比如说n位。这样,传输时,按每n位划分为一个时间片,发送端在一个时间片中发送一个字符,接收端则在一个时间片中接收一个字符。

    同步传输时,一个信息帧中包含许多字符,每个信息帧用同步字符作为开始,一般将同步字符和空字符用同一个代码。在整个系统中,由一个统一的时钟控制发送端的发送和空字符用同一个代码。接收端当然是应该能识别同步字符的,当检测到有一串数位和同步字符相匹配时,就认为开始一个信息帧,于是,把此后的数位作为实际传输信息来处理。

    2、面向字符的同步协议(IBM的BSC协议)

    20030414_106-b-1.gif

    该协议规定了10个特殊字符(称为控制字符)作为信息传输的标志。其格式为

    SYN SOH 标题 STX 数据块 ETB/ETX 块校验

    SYN:同步字符(Synchronous character),每帧可加1个(单同步)或2个(双同步)同步字符。

    SOH:标题开始(Start of Header)。

    标题:Header,包含源地址(发送方地址)、目的地址(接收方地址)、路由指示。

    STX:正文开始(Start of Text)。

    数据块:正文(Text),由多个字符组成。

    ETB:块传输结束(end of transmission block), 标识本数据块结束。

    ETX:全文结束(end of text),(全文分为若干块传输)。

    块校验:对从SOH开始,直到ETB/ETX字段的检验码。

    3、面向bit的同步协议(ISO的HDLC)

    20030414_106-b-2.gif

    一帧信息可以是任意位,用位组合标识帧的开始和结束。 帧格式为:

    F场 A场 C场 I场 FC场 F场

    F场:标志场;作为一帧的开始和结束,标志字符为8位,01111110。

    A场:地址场,规定接收方地址,可为8的整倍位。接收方检查每个地址字节的第1位,如果为"0",则后边跟着另一

    个地址字节。若为"1",则该字节为最后一个地址字节。

    C场:控制场。指示信息场的类型,8位或16位。若第1字节的第1位为0,则还有第2个字节也是控制场。

    I场:信息场。要传送的数据。

    FC场:帧校验场。16位循环冗余校验码CRC。除F场和自动插入的"0"位外,均参加CRC计算。

    4、同步通信的"0位插入和删除技术"

    在同步通信中,一帧信息以一个(或几个)特殊字符开始,例如,F场=01111110B。

    但在信息帧的其他位置,完全可能出现这些特殊字符,为了避免接收方把这些特殊字符误认为帧的开始,发送方采用“0位插入技术",相应地,接收方采用"0位删除技术"。

    发送方的0位插入:除了起始字符外,当连续出现5个1时,发送方自动插入一个0。使得在整个信息帧中,只有起始字符含有连续的6个1。

    接收方的"0位删除技术":接收方收到连续6个1,作为帧的起始,把连续出现5个1后的0自动删除。

    5、同步通信的"字节填充技术"

    设需要传送的原始信息帧为:

    SOT DATA EOT

    节填充技术采用字符替换方式,使信息帧的DATA中不出现起始字符SOT和结束字符EOT。

    设按下表方式进行替换:

    DATA中的原字符   替换为

    SOT        ESC X

    EOT         ESC Y

    ESC         ESC Z

    其中,ESC=1AH,X、Y、Z可指定为任意字符(除SOT、EOT、ESC外)。

    发送方按约定方式对需要发送的原始帧进行替换,并把替换后的新的帧发送给接收方。例如图所示:

    20030414_106-b-3.gif

    接收方按约定方式进行相反替换,可以获得原始帧信息。

    6、异步通信和同步通信的比较

    (1)异步通信简单,双方时钟可允许一定误差。同步通信较复杂,双方时钟的允许误差较小。

    (2)异步通信只适用于点 点,同步通信可用于点 多。

    (3)通信效率:异步通信低,同步通信高。

    posted on 2006-12-18 23:43 junky 阅读(10599) 评论(0)  编辑  收藏 所属分类: 计算机科学,编程思想

    展开全文
  • uart i2sRGM i2c异步 同步,单双工,全双工概念 i2s ,rgm以太网,uart 有tx,rx,即可同时发,又可同时收, i2c,只有SDA一根数据线,只能单向读或写,不能同时读写, 同步和异步是啥意思,后面再酝酿写清楚 ...

    uart i2sRGM i2c异步 同步,单双工,全双工概念

    i2s ,rgm以太网,uart 有tx,rx,即可同时发,又可同时收,
    i2c,只有SDA一根数据线,只能单向读或写,不能同时读写,
    同步和异步是啥意思,后面再酝酿写清楚

    展开全文
  • 1.同步 1.1.基本用法 例子1.基本用法 RedisClient client = RedisClient.create("redis://localhost"); (1) StatefulRedisConnection<String, String> connection = client.connect(); (2) Redis...

    本文章基于Redis 6.0.9版本,Lettuce 6.0.1.RELEASE版本

    目录

    1.同步

    1.1.基本用法

    例子1.基本用法

    1.2.RedisURI

    1.3.Exceptions

    1.4.例子

    示例2.使用host和port并将默认超时设置为20秒

    例子3.使用RedisURI

    例子4. SSL RedisURI

    例子5.String RedisURI

    2.异步

    2.1.动机

    2.2.了解异步性

    2.3.异步性对同步API的影响

    2.4.结果句柄

    例子1.使用CompletableFuture的第一步

    例子2.使用带有CompletableFuture的监听器

    例子3.使用消费者将来的监听器

    2.4.用Lettuce创造future

    2.5.消费future

    例子4.获取一个键

    例子5.阻塞同步

    例子6.使用消费者监听器和GET

    例子7.将消费者lambda与GET一起使用

    例子8.异步监听器通知

    2.6.同步future

    2.7.阻塞同步

    例子9.异步获取多个键

    例子10.使用RedisFuture.await等待结果

    2.8.链同步

    例子11.Future chaining

    例子12.与lambda表达式Future chaining

    例子13.从Upstream和Replica(复制节点)中读取并继续第一个响应

    2.9.错误处理

    例子14.将来的监听器接收结果和错误对象

    例子15.使用异常处理程序的Future恢复

    2.10.例子

    例子16.基本操作

    例子17.等待超时

    例子18.在RedisFuture中使用一个监听器


    1.同步

    1.1.基本用法

    例子1.基本用法

    RedisClient client = RedisClient.create("redis://localhost");          (1)
    
    StatefulRedisConnection<String, String> connection = client.connect(); (2)
    
    RedisCommands<String, String> commands = connection.sync();            (3)
    
    String value = commands.get("foo");                                    (4)
    
    ...
    
    connection.close();                                                    (5)
    
    client.shutdown();                                                     (6)

    说明

    1. 创建RedisClient实例,并提供一个指向本地主机端口6379(默认端口)的Redis URI。
    2. 打开Redis Standalone连接。 从初始化的RedisClient使用端点。
    3. 获取用于同步执行的命令API。 Lettuce也支持异步和反应式执行模型。
    4. 发出GET命令以获取键 foo
    5. 完成后,关闭连接。 这通常发生在应用程序的最后。 连接被设计为长寿命的。
    6. 关闭客户端实例以释放线程和资源。 这通常发生在应用程序的最后。

    每个Redis命令是通过一个或多个名称与小写Redis命令名称相同的方法实现的。 具有多个可修改结果类型的修饰符的复杂命令包括CamelCased修饰符作为命令名称的一部分,例如 zrangebyscorezrangebyscoreWithScores

    Redis连接被设计为长期存在并且是线程安全的,如果连接丢失,将重新连接,直到调用 close() 为止。 成功重新连接后,将(重新)发送尚未超时的未决命令。

    所有连接均从其RedisClient继承默认超时,并且当非阻塞命令在超时到期前未能返回结果时,将抛出RedisException。 超时默认为60秒,可以在RedisClient或每个连接中更改。 同步方法将抛出RedisCommandExecutionException ,以防Redis响应错误。 Redis响应错误时,异步连接不会引发异常。

    1.2.RedisURI

    RedisURI包含host/port,并且可以携带身份验证/数据库详细信息。 连接成功后,您将获得身份验证,然后选择数据库。 这适用连接断开后也重新建立连接后。

    还可以从URI字符串创建Redis URI。 支持的格式有:

    • redis://[password@]host[:port][/databaseNumber] 纯文本Redis连接
    • rediss://[password@]host[:port][/databaseNumber] SSL Redis连接
    • redis-sentinel://[password@]host[:port][,host2[:port2]][/databaseNumber]#sentinelMasterId for using Redis Sentinel
    • redis-socket:///path/to/socket Unix Domain Socket 连接到Redis

    1.3.Exceptions

    如果来自Redis的exception/error响应,您将收到包含错误消息的RedisException 。 RedisException 是RuntimeException

    1.4.例子

    示例2.使用host和port并将默认超时设置为20秒

    RedisClient client = RedisClient.create(RedisURI.create("localhost", 6379));
    client.setDefaultTimeout(20, TimeUnit.SECONDS);
    
    // …
    
    client.shutdown();

    例子3.使用RedisURI

    RedisURI redisUri = RedisURI.Builder.redis("localhost")
                                    .withPassword("authentication")
                                    .withDatabase(2)
                                    .build();
    RedisClient client = RedisClient.create(redisUri);
    
    // …
    
    client.shutdown();

    例子4. SSL RedisURI

    RedisURI redisUri = RedisURI.Builder.redis("localhost")
                                    .withSsl(true)
                                    .withPassword("authentication")
                                    .withDatabase(2)
                                    .build();
    RedisClient client = RedisClient.create(redisUri);
    
    // …
    
    client.shutdown();

    例子5.String RedisURI

    RedisURI redisUri = RedisURI.create("redis://authentication@localhost/2");
    RedisClient client = RedisClient.create(redisUri);
    
    // …
    
    client.shutdown();

    2.异步

    2.1.动机

    异步方法使您可以利用更好的系统资源,而不是浪费线程等待网络或磁盘I/O。 可以充分利用线程来执行其他工作。 Lettuce通过在基于netty的客户端(多线程,事件驱动的I/O框架)上构建客户端来促进异步性。 所有通信都是异步处理的。 一旦基金会能够同时处理命令,便可以方便地利用异步性。 将阻塞和同步的工作软件转换为并发处理系统要困难得多。

    2.2.了解异步性

    异步性允许其他处理在传输完成和传输响应处理之前继续进行。 这意味着,在Lettuce其是Redis的情况下,可以连续发出多个命令,而无需等待完成前面的命令。 这种操作模式也称为流水线(Pipelining)。 以下示例应该给您一种操作模式的印象:

    • 给定客户A和客户B
    • 客户端A触发命令 SET A=B
    • 客户端B在客户端A命令的同时触发 SET C=D
    • Redis从客户端接收命令 A
    • Redis从客户端接收命令 B
    • Redis处理 SET A=B 并对客户端A做出响应
    • 客户端A接收响应并将响应存储在响应句柄中
    • Redis处理SET C=D并响应客户端B
    • 客户端B接收响应并将响应存储在响应句柄中

    上例中的两个客户端可以是应用程序中的两个线程或连接,也可以是两个物理上分离的客户端。

    客户端可以通过单独的进程(processes),线程(threads),事件循环(event-loops),参与者(actors),光纤(fibers)等相互并行操作。Redis串行处理传入的命令,并且大多数情况下是单线程操作。 这意味着,命令将按照接收到的顺序进行处理,并具有我们稍后将介绍的某些特征。

    让我们以简化的示例为例,并通过一些程序流程细节对其进行增强:

    • 给定客户A
    • 客户端A触发命令 SET A=B
    • 客户端A使用异步API并可以执行其他处理
    • Redis从客户端A接收命令
    • Redis处理SET A=B并对客户端A做出响应
    • 客户端A接收响应并将响应存储在响应句柄中
    • 客户端A现在可以访问对其命令的响应而无需等待(非阻塞)

    客户端A从不等待命令结果中受益,因此它可以处理计算工作或发出另一个Redis命令。 只要响应可用,客户端就可以使用命令结果。

    2.3.异步性对同步API的影响

    尽管本指南可帮助您了解异步API,但值得学习对同步API的影响。 同步API的一般方法与异步API相同。 在这两种情况下,都使用相同的工具来调用命令并将其传输到Redis服务器。 唯一的区别是使用同步API的调用方的阻塞行为。 阻塞发生在命令级别,仅影响命令完成部分,这意味着使用同步API的多个客户端可以在同一连接上同时调用命令,而不会彼此阻塞。 在处理命令响应的那一刻,对同步API的调用将被解除阻塞。

    • 给定客户A和客户B
    • 在同步API上执行Client A触发命令SET A=B并等待结果
    • 客户端B在同步API上同时触发客户端A命令SET C=D并等待结果
    • Redis从客户端A接收命令
    • Redis从客户端B接收命令
    • Redis处理SET A=B并对客户端A做出响应
    • 客户端A收到响应并取消阻塞客户端A的程序流程
    • Redis处理SET C=D并响应OK给客户端B
    • 客户端B收到响应并取消阻塞客户端B的程序流

    但是,在某些情况下,您不应该在线程之间共享连接,以免产生副作用。 情况是:

    • 禁用flush-after-command以提高性能
    • 使用阻塞操作,例如BLPOP。 阻塞操作会在Redis上排队,直到可以执行为止。 当一个连接被阻塞时,其他连接可以向Redis发出命令。 一旦一个命令解除阻塞命令(表示LPUSHRPUSH 命中了列表),被阻塞的连接即被解除阻塞,此后可以继续进行。
    • 事务次数
    • 使用多个数据库

    2.4.结果句柄

    异步API上的每个命令调用都会创建RedisFuture<T> ,可以将其取消,等待和订阅(监听器)。 CompleteableFuture<T>RedisFuture<T>是指向结果的指针,该结果最初未知,因为其值的计算尚未完成。RedisFuture<T>提供用于同步和链接(chaining)的操作。

    例子1.使用CompletableFuture的第一步

    CompletableFuture<String> future = new CompletableFuture<>();
    
    System.out.println("Current state: " + future.isDone());
    
    future.complete("my value");
    
    System.out.println("Current state: " + future.isDone());
    System.out.println("Got value: " + future.get());

    该示例打印以下行:

    Current state: false
    Current state: true
    Got value: my value

    将监听器附加到将来允许链接(chaining)上。Promises可以对future使用synonymous,但并非每个future都是一个promise。 一个promise保证了callback/notification,因此它已经到了它的名字。

    一个简单的监听器,在将来完成后会被调用:

    例子2.使用带有CompletableFuture的监听器

    final CompletableFuture<String> future = new CompletableFuture<>();
    
    future.thenRun(new Runnable() {
        @Override
        public void run() {
            try {
                System.out.println("Got value: " + future.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    });
    
    System.out.println("Current state: " + future.isDone());
    future.complete("my value");
    System.out.println("Current state: " + future.isDone());

    value处理从调用者移到监听器,然后由编译future的任何人调用。 该示例打印以下行:

    Current state: false
    Got value: my value
    Current state: true

    上面的代码需要处理异常,因为对 get() 方法的调用可能导致异常。 计算Future<T> 期间引发的异常在ExecutionException中传输。 可能引发的另一个异常是InterruptedException。 这是因为对get()的调用正在阻塞调用,并且被阻塞的线程可以随时中断。 只要考虑一下系统关闭。

    自Java 8起,CompletionStage<T>类型允许对期货进行更为复杂的处理。CompletionStage<T>可以使用,转换和构建价值处理链(chain)。 上面的代码可以用以下样式在Java 8中重写:

    例子3.使用消费者将来的监听器

    CompletableFuture<String> future = new CompletableFuture<>();
    
    future.thenAccept(new Consumer<String>() {
        @Override
        public void accept(String value) {
            System.out.println("Got value: " + value);
        }
    });
    
    System.out.println("Current state: " + future.isDone());
    future.complete("my value");
    System.out.println("Current state: " + future.isDone());

    该示例打印以下行:

    Current state: false
    Got value: my value
    Current state: true

    您可以在Java 8 API文档中找到CompletionStage<T>类型的完整参考。

    2.4.用Lettuce创造future

    Lettuce future 可用于初始和链接(chaining)操作。 使用Lettuce future时,您会注意到非阻塞行为。 这是因为所有的 I/O 和命令处理都是使用netty EventLoop异步处理的。LettuceRedisFuture<T>扩展了CompletionStage<T>,因此所有基本类型的方法均可用。

    Lettuce在Standalone,Sentinel,Publish/Subscribe和Cluster API上展示其future。

    连接到Redis非常简单:

    RedisClient client = RedisClient.create("redis://localhost");
    RedisAsyncCommands<String, String> commands = client.connect().async();

    下一步,从键获取值需要GET操作:

    RedisFuture<String> future = commands.get("key");

    2.5.消费future

    使用future时,您要做的第一件事就是消费future。 消费future意味着获得value。 这是一个阻塞调用线程并输出值的示例:

    例子4.获取一个键

    RedisFuture<String> future = commands.get("key");
    String value = future.get();
    System.out.println(value);

    调用get()方法(pull-style)至少会阻塞调用线程,直到计算出该值为止,但在最坏的情况下会无限期地阻塞该线程。 使用超时永远是不浪费线程的好主意。

    例子5.阻塞同步

    try {
        RedisFuture<String> future = commands.get("key");
        String value = future.get(1, TimeUnit.MINUTES);
        System.out.println(value);
    } catch (Exception e) {
        e.printStackTrace();
    }

    该示例最多等待1分钟,以便将来完成操作。 如果超时超过,则抛出TimeoutException 来发出超时信号。

    Future也可以按(push style)方式消费,这意味着当RedisFuture<T>完成时,将触发后续操作:

    例子6.使用消费者监听器和GET

    RedisFuture<String> future = commands.get("key");
    
    future.thenAccept(new Consumer<String>() {
        @Override
        public void accept(String value) {
            System.out.println(value);
        }
    });

    或者,用Java 8 lambdas编写:

    例子7.将消费者lambda与GET一起使用

    RedisFuture<String> future = commands.get("key");
    
    future.thenAccept(System.out::println);

    Lettuce future在netty EventLoop上完成。 除了以下情况外,在默认线程上使用和链接(chaining)future总是一个好主意:阻塞/长时间运行操作。 根据经验,切勿阻塞事件循环。 如果您需要使用阻塞调用来chaining future,请使用thenAcceptAsync()/thenRunAsync()方法将处理分叉到另一个线程。 …async()方法需要一个线程基础架构来执行,默认情况下使用ForkJoinPool.commonPool()ForkJoinPool 是静态构造的,不会随着负载的增加而增长。 使用默认执行器几乎总是更好的主意。

    例子8.异步监听器通知

    Executor sharedExecutor = ...
    RedisFuture<String> future = commands.get("key");
    
    future.thenAcceptAsync(new Consumer<String>() {
        @Override
        public void accept(String value) {
            System.out.println(value);
        }
    }, sharedExecutor);

    2.6.同步future

    使用Future的关键是同步。 Future通常用于:

    • 触发多个调用,而不必急于等待predecessors(批处理)
    • 完全不等待结果即调用命令(Fire&Forget)
    • 同时调用命令并执行其他计算(Decoupling)
    • 将并发添加到某些计算工作中(并发)

    有几种方法可以等待或等待将来完成时得到通知。 某些同步技术适用于您想要使用future的某些动机。

    2.7.阻塞同步

    如果您对系统的某些部分执行批处理/添加(batching/add并发,则阻塞同步将很方便。 批处理的一个示例可以是设置/检索(setting/retrieving多个值,然后在处理中的某个点之前等待结果。

    例子9.异步获取多个键

    List<RedisFuture<String>> futures = new ArrayList<RedisFuture<String>>();
    
    for (int i = 0; i < 10; i++) {
        futures.add(commands.set("key-" + i, "value-" + i));
    }
    
    LettuceFutures.awaitAll(1, TimeUnit.MINUTES, futures.toArray(new RedisFuture[futures.size()]));

    上面的代码不会等到某个命令完成后才发出另一个命令。 发出所有命令后完成同步。 通过省略对LettuceFutures.awaitAll()的调用,可以轻松地将示例代码转换为Fire&Forget模式。

    也可以等待将来执行一次,这意味着可以选择等待特定时间但不会引发异常:

    例子10.使用RedisFuture.await等待结果

    RedisFuture<String> future = commands.get("key");
    
    if(!future.await(1, TimeUnit.MINUTES)) {
        System.out.println("Could not complete within the timeout");
    }

    调用await()更友好,因为在阻塞的线程被中断的情况下,它仅抛出InterruptedException 。 您已经熟悉用于同步的get()方法,因此我们不会为您困扰。

    最后,还有另一种以阻塞方式同步future的方法。 主要警告是您将负责处理线程中断。 如果您不处理该方面,则如果系统处于运行状态,则将无法正确关闭系统。

    RedisFuture<String> future = commands.get("key");
    while (!future.isDone()) {
        // do something ...
    }

    尽管isDone()方法的主要目的不是用于同步,但在执行命令时执行其他计算工作可能会很方便。

    2.8.链同步

    可以以非阻塞方式同步/链接(synchronized/chained)Future,以提高线程利用率。 链接(Chaining )在依赖事件驱动特征的系统中效果很好。 Future链(chaining)建立了一个或多个按顺序执行的future链(chain),每个链(chain)成员处理计算中的一部分。 CompletionStage<T> API提供了多种方法来链接和转换future。 可以使用thenApply()方法对值进行简单的转换:

    例子11.Future chaining

    future.thenApply(new Function<String, Integer>() {
        @Override
        public Integer apply(String value) {
            return value.length();
        }
    }).thenAccept(new Consumer<Integer>() {
        @Override
        public void accept(Integer integer) {
            System.out.println("Got value: " + integer);
        }
    });

    或者,用Java 8 lambdas编写:

    例子12.与lambda表达式Future chaining

    future.thenApply(String::length)
        .thenAccept(integer -> System.out.println("Got value: " + integer));

    thenApply()方法接受一个将值转换为另一个值的函数。 final的thenAccept()方法使用该值进行最终处理。

    您已经从前面的示例中看到了thenRun()方法。 如果数据对您的流程不重要,那么thenRun()方法可用于处理将来的完成情况:

    future.thenRun(new Runnable() {
        @Override
        public void run() {
            System.out.println("Finished the future.");
        }
    });

    如果要在Runnable 中执行阻塞调用,请记住在自定义执行器(Executor)上执行Runnable

    另一个值得一提的链接方法是“either-or”链接。 CompletionStage<T>上有几种...Either()方法,请参阅Java 8 API文档以获取完整参考。 “either-or”模式消耗已完成的第一个future的值。 一个很好的例子可能是两个服务返回相同的数据,例如,Upper-Replica场景,但是您希望尽快返回数据:

    例子13.从Upstream和Replica(复制节点)中读取并继续第一个响应

    RedisStringAsyncCommands<String, String> upstream = upstreamClient.connect().async();
    RedisStringAsyncCommands<String, String> replica = replicaClient.connect().async();
    
    RedisFuture<String> future = upstream.get("key");
    future.acceptEither(replica.get("key"), new Consumer<String>() {
        @Override
        public void accept(String value) {
          System.out.println("Got value: " + value);
        }
    });

    2.9.错误处理

    错误处理是每个现实应用程序中必不可少的组件,应从一开始就加以考虑。 Future提供了一些处理错误的机制。

    通常,您希望通过以下方式做出反应:

    • 返回默认值
    • 使用future的备份
    • 重试future

    RedisFuture<T>的传输异常(如果发生)。 调用get()方法将引发发生的异常包装在ExecutionException 中(这与Lettuce 3.x不同)。 您可以在CompletionStage的Javadoc中找到更多详细信息。

    通过使用 handle()方法将以下代码运行为异常后,以下代码将恢复为默认值:

    例子14.将来的监听器接收结果和错误对象

    future.handle(new BiFunction<String, Throwable, String>() {
        @Override
        public Integer apply(String value, Throwable throwable) {
            if(throwable != null) {
              return "default value";
            }
            return value;
        }
    }).thenAccept(new Consumer<String>() {
        @Override
        public void accept(String value) {
            System.out.println("Got value: " + value);
        }
    });

    更复杂的代码可以代表throwable类型决定要返回的值,这是使用exceptionally()方法的快捷示例:

    例子15.使用异常处理程序的Future恢复

    future.exceptionally(new Function<Throwable, String>() {
        @Override
        public String apply(Throwable throwable) {
            if (throwable instanceof IllegalStateException) {
                return "default value";
            }
    
            return "other default value";
        }
    });

    Retrying future和使用future进行恢复不属于Java 8 CompleteableFuture<T>的一部分。 有关异常处理的简便方法,请参见Reactive API

    2.10.例子

    例子16.基本操作

    RedisAsyncCommands<String, String> async = client.connect().async();
    RedisFuture<String> set = async.set("key", "value");
    RedisFuture<String> get = async.get("key");
    
    set.get() == "OK"
    get.get() == "value"

    例子17.等待超时

    RedisAsyncCommands<String, String> async = client.connect().async();
    RedisFuture<String> set = async.set("key", "value");
    RedisFuture<String> get = async.get("key");
    
    set.await(1, SECONDS) == true
    set.get() == "OK"
    get.get(1, TimeUnit.MINUTES) == "value"

    例子18.在RedisFuture中使用一个监听器

    RedisStringAsyncCommands<String, String> async = client.connect().async();
    RedisFuture<String> set = async.set("key", "value");
    
    Runnable listener = new Runnable() {
        @Override
        public void run() {
                ...;
        }
    };
    
    set.thenRun(listener);

     

    展开全文
  • 总得来说,同步异步出现在以下几个领域:1 计算机网络。数据通信技术中有同步通信与异步通信。同步通信简单的说就是你在发送数据时候我必须同时接受。这个过程有精确的时钟控制。而异步通信是你在发数据时候必须加上...

    总得来说,同步异步出现在以下几个领域:

    1  计算机网络。

    数据通信技术中有同步通信与异步通信。同步通信简单的说就是你在发送数据时候我必须同时接受。这个过程有精确的时钟控制。而异步通信是你在发数据时候必须加上开始与结束符号,这样我才可以接受,异步通信没有时钟控制。因为没有了时钟的控制(额外硬件),所以成本低,设备简单,但是传输效率较低。(开始与结束符占了开销)。

    在网络协议(network protocol)的三大组成部分:语法,语义,同步。这时候同步指的是事件实现的顺序。比如建立tcp连接时候的三次握手实现顺序。

    2   操作系统。

    中断系统的一个特点就是可以对异步事件响应。异步事件指的是断断续续,随机,没有时序关系的事件。同步事件反之,一个事件从头到尾顺序执行,没有间断。

    进程间的关系有同步与互斥。同步就是多个进程协调完成一个任务。比如,司机与售票员关系。司机停车---售票员开门----乘客上车---售票员关门---司机开车。在这个过程中任务就是拉乘客。司机和售票员作为两个进程协调工作。互斥指的是多个进程竞争同一个资源。这时资源叫做临界资源(任何时刻只允许一个进程访问,三个线程可以同时时一个变量iChange减1,但任何时间只允许一个对其进行操作,火车售票问题如果不加同步最终票数会出现负值。)。

    在现代操作系统中,有并发性,共享性,虚拟性,不确定性四大基础特征。而程序并发活动的实现是异步(一个程序走走停停),并发控制的时候需要用到同步技术。(Java多线程中可以使用Synchronized实现同步控制),所以并发控制需要同步,并发的实现是异步,同步过多又会导致死锁。在并发领域有一句经典的话,并发执行的可串行化。那么并行是什么?并行才是真正的并发。并发只不过在占用时间片不同上实现的。

    I/O模型中,频繁出现的有同步与异步,阻塞与非阻塞。要想弄清这个问题,必须了解冯诺依曼体系结构与进程状态模型。首先理解I/O在计算机体系中作用。

    20d7b12593ef879389f64cf5bcf3f084.png

    一个输入操作包含两个过程:

    1   等待数据准备好

    2   从内核向进程复制数据。

    同步与异步在I/O中指的是一种数据访问机制。

    同步指的是主动请求后等待I/O,数据就绪后读写必须阻塞。

    异步指的是主动请求后,可处理其他任务,等I/O完毕后通知。

    阻塞指的是进程访问的数据未就绪,进程必须等待。

    非阻塞指的是进程访问数据未就绪,进程可以不用等待。

    e420af6e75bb608ea82f087cbe5ad658.png

    进程一般有五种状态,创建进程,此时进程在就绪队列中等待cpu调度,当在cpu上执行时,此时为运行态,运行过程中可能遇到I/O请求此时进入阻塞状态,或者进程执行完,进入死亡状态。阻塞的时候,当所需资源满足时,从阻塞状态转化为就训态。如此反复。

    有了以上基础知识的积淀,现在来看常用I/O模型。

    91eedb0adb4c9c43e1ddc0b429b7ccdd.png

    完整模型请参考《Unix网络编程卷1》P127.

    举个例子吧:纯概念实在难以理解。

    如果说我(某个进程)去食堂吃饭(任务A),吃完后要去图书馆(任务B)。也可以去教室。(任务C)等待阿姨把饭做好。

    阻塞式I/O就是我一直在等阿姨做饭。直到吃上饭。

    非阻塞式I/O就是我在等的时候,会一直问阿姨饭好了没有,直到吃上饭。

    同步阻塞式I/O和同步非阻塞式I/O都会使得进程阻塞。(任务卡在A那里不动了)

    I/O复用涉及到select,poll函数,由于未深入理解,例子没想到。

    信号驱动式就是我在等的时候,也在等其他信号,比如阿姨使眼色我让我吃饭,直到吃上饭。

    异步I/O就是我在等的时候,可以去图书馆也可以去教室,饭好了后,阿姨会叫我吃饭。(发起任务A到通知结束A时候过程中可以执行选择性执行A,B,C,而不会把阻塞到任务A那里)。

    看了这么多,那究竟什么是同步与异步呢?必须放在具体的环境以及项目中去深入理解。

    这是我所知道的同步与异步在计算机中出现的地方,文中有很多观点是我自己理解的,可能不符合真实的含义,希望大家帮我纠正下。不甚感激。个人水平实在有限,没有贡献关于同步异步的代码。

    这是我的第一篇技术博客,没想到竟然花费了2个多小时。发现自己理解的---写出来----说出来---说出来让别人理解的难度水平在递增,写作过程也是一个梳理知识体系以及思考的过程。希望自己可以坚持写博客。

    展开全文
  • 原标题:浅谈socket同步和异步、阻塞非阻塞、I/O模型在进行网络编程时,常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式同步/异步主要针对C端:同步c端发出一个功能调用时,在没有得到...
  • STM8L的硬件I2C(三)硬件I2C中断读写 1、I2C初始化 关于I2C初始化的流程,标准库中的注释写的非常清晰: * 1. Enable peripheral clock using CLK_PeripheralClockConfig(CLK_Peripheral_I2Cx, * ENABLE) ...
  • 同步代码和异步代码的执行顺序 要弄懂异步api要先搞懂它和同步api的区别,我们先从代码执行顺序说起。同步代码从上到下执行,前面的代码会阻塞后面代码的执行,比如我用for语句循环打印10个数然后再打印一条输出语句...
  • 1.同步异步同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值...
  • 首先我们要明确的是,同步和异步都是针对两个或者两个以上的事物来说的。比如当我们在网上购物看中一件物品,然后去浏览该商品详情的时候,首先页面会先发送一个请求,后台服务器查询对应商品的相关数据,然后前端...
  • binary log dump 线程2)从节点I/O线程3)从节点SQL线程1.2 GTID主从异步复制GTID的优点1.3 Mysql的主从异步复制1.4 Mysql的全同步1.4 Mysql的半同步2 mysql的MHA高可用2.1 简介2.2 特点 1 Mysql数据库的主从复制...
  • 到目前为止,我们已经讨论了SPI通信UART通信的基础知识,因此现在让我们进入本系列的最后一个协议,即集成电路总线或I2C。 如果你在项目里使用OLED显示器,气压传感器或陀螺仪/加速度计模块,那你很可能会发现...
  • I2C Inter-Integrated Circuit:内部集成电路总线 由SCL、SDA两根线连接,半双工同步串行总线;**空闲时:**SDA、SCL都是高电平;**开始传输:**SCL高电平时,SDA下降沿触发开始传输;**结束传输:**SCL高电平时,...
  • 同步获取异步任务结果 思路:首先从jdk提供的框架代码入手,然后再自己定义一个, 原创qq作者:855189478 1、CountDownLatch 使用同步框架可以实现同步,但是不能获取到异步的结果 参考代码如下: import java....
  • 异步复制MySQL复制默认是异步复制,Master将事件写入binlog,提交事务,自身并不知道slave是否接收是否处理;缺点:不能保证所有事务都被所有slave接收。同步复制Master提交事务,直到事务在所有slave都已提交,才会...
  • IO——同步异步、阻塞、非阻塞IO类型IO分类介绍Blocking IO——阻塞型的IONonBlocking IO——非阻塞的IO IO类型 一般情况下:IO又五种类型 BlockingIO: 阻塞型的IO NonBlockingIO:非阻塞型的IO IO multiplexing ...
  • So I'm locked to a python 3.6.2 interpreter that follows my desktop application.What I want is to call an async function from a synchronized method or function.When calling the python function from th...
  • 而只有前面定义的异步I/O模型与这里的异步I/O操作 总结 同步或者异步I/O主要是指访问数据的机制(即实际I/O操作的完成方式),同步一般指主动请求并等待I/O操作完毕的方式,I/O操作 未完成前,会导致应用进程挂起;...
  • 什么是异步呢,很好理解,一般的我们的代码执行的顺序是同步的,也就是执行完这条代码再执行下一条代码,而异步就是我们在某个时间点执行某个代码,而不是顺序执行 创建一条我们比较熟的预加载,这里就是一个典型的...
  • </Appende 【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】 ... rs> ...混合同步和异步日志 ...Log4j-2.9及更高版本在类路径上需要...可以在配置中组合同步和异步记录器。这为您提供.
  • 同步 FIFO 实现较为直接,如下图所示,一个 FIFO 内部实现了 RAM 一个控制读写的控制端,普通的随机存储器不一样的是,FIFO 内部需要自动产生读写地址。 控制端产生空、满信号。因此如何实现控制端去产生空满...
  • 串口通信基本概念(一)——串行与并行通信,同步异步通信 一、串口通信简介 串口通信,顾名思义也就是利用串行接口进行通信。串行接口指串口按位(bit)发送接收字节。尽管比按字节(byte)传输的并行通信慢,...
  • 异步/同步(被调用者),阻塞/非阻塞(调用者)https://mp.weixin.qq.com/s/TW82I31CVRbKOwJGnTTP8A原创:wangzenghuang[深夜里的程序猿](javascript:void(0);)*4月17日*![]...
  • I2C协议简单总结

    2021-03-17 16:06:05
    文章目录基础概念总线、串行总线、串行总线的同步/异步模式、常见串行总线I2C---一种简单、双向二线制同步串行总线I2C 数据传输---主器件提供时钟并发起传输,通过寻址数据通知对应从片接受或发送数据I2C总线的协议...
  • 参考:带你快速对比SPI、UART、I2C通信的区别与应用! 作者:一口Linux 网址:https://mp.weixin.qq.com/s/4_RSM2jk2W6nTboO1W8HCw 电子设备之间的通信就像人类之间的交流,双方都需要说相同的语言。在电子产品中,...
  • 在调试通信的这段时间里,自己接触到了很多有关通信的专有名词,SCI,SPI,I2C,UART,CAN,RS232,RS485等等。自己在项目中使用TMS320F280049对SCI,I2C,CAN进行了通讯调试,包括底层配置,应用函数编写及通讯测试...
  • DSP28377 I2C开发笔记

    2021-07-26 11:42:46
    I2C模块支持任何与I2C兼容的从设备或主设备。图20-1显示了多个I2C模块的示例,这些模块用于从一个设备到其他设备的双向传输。 连接到I2C总线的每个设备都由一个唯一的地址来识别。根据设备的功能,每个设备可以...
  • 文章目录一、JS单线程异步编程1、进程线程:2、JS是单线程异步编程**代码执行过程中,遇到一个异步编程的任务**:**常见情景一:Promise产生的实例****常见情景2:async/await:是promise+generator的语法糖**二、...
  • 阻塞I/O(blocking IO) 非阻塞I/O (nonblocking I/O) 信号驱动I/O (signal driven I/O (SIGIO)) I/O 多路复用 (I/O multiplexing) 异步I/O (asynchronous I/O) 前面已经介绍了阻塞IO、非阻塞IO异步IO,接着再...
  • 同步和异步是什么意思?Web 应用程序通常要处理许多请求,这些请求在短时间内来自不同的客户端。为避免处理延迟,必须考虑并行处理多个请求,这通常称为“并发”。在本文中,我将继续使用 Web 应用程序作为例子,但...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 130,477
精华内容 52,190
关键字:

同步和异步i2c