出现这个问题真的很难受,搞了好久,其实不同的机型有不同的效果,我在魅族 手机 华硕手机 华为p8上都没有出现这样的问题
首先,造成这个问题的 BUG RocketMQ 官方已经在 3月16号 的这个提交中修复了,这里只是探讨一下在修复之前造成问题的具体细节,更多的上下文可以参考我之前写的 《RocketMQ Consumer 启动时都干了些啥?》 ,这篇文章讲解了 RocketMQ 的 Consumer 启动之后都做了哪些操作,对理解本次要讲解的 BUG 有一定的帮助。
之前在 【Android 异步操作】手写 Handler ( 消息队列 MessageQueue | 消息保存到链表 | 从链表中获取消息 ) 中 , 模仿 Android 的 MessageQueue 手写的 MessageQueue , 使用了如下同步机制 ,
初始化 HandlerThread , 特别注意 , 初始化完成后 , 紧跟着调用该线程的 start() 方法启动 ;
内容简述 类似Binder机制,MessageQueue、Looper也有底层的C++实现,涉及文件管道和驱动等。 以下仅从Java层的Looper、Handler和MessageQueue等相关类
我们知道MessageQueue就一个构造函数 代码在MessageQueue.java 68行
服务端 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Messaging; namespace BaseOfWcf { class Program { static void Main(string[] args) { //if (!MessageQueue.Exists(@".\MYF
rocketmq-all-4.6.0-source-release/client/src/main/java/org/apache/rocketmq/client/consumer/LitePullConsumer.java
出现了重复消费的问题,同一个消息被重复消费了多次,导致了用户端收到了多条重复的消息,最终排查发现,是因为消费者在处理消息的方法onMessage中有异常没有捕获到,导致异常上抛,被consumeMessage捕获并判定为消费失败,从而放到了重试队列当中进行重试,下面我们就来看看RocketMq中会引起消息重试的两种情况,内部异常和消费超时。
Looper 是 线程本地变量 , 在每个线程中 , 可以通过线程调用 ThreadLocal 变量的 get 方法获取该线程对应的对象副本 , 调用 ThreadLocal 变量的 set 方法 , 设置该线程对应类型的对象副本 ;
上图中我们在子线程中创建一个Handler对象,会抛出异常。异常信息说明不能在没有调用Looper.prepare()的线程中创建Handler对象。
在 Android 系统中的 Handler 机制 中 , 涉及到了 Handler , Message , Looper , MessageQueue 等组件 , 其中 MessageQueue 是消息队列 , 其中包含了很多 单链表 元素 ;
1.主题队列是如何分配的? 2.什么时候会进行负载均衡? 3.负载均衡后是否会导致消息重复消费?
Handler是Android中处理异步消息的机制。Looper、Handler、MessageQueue、Message概括来说就是:Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息Message,然后回调相应的消息处理函数,而消息的创建者就是一个或多个Handler,执行完成一个消息后则继续循环。
在有些场景下,使用 MQ 需要保证消息的顺序性,比如在电商系统中,用户提交订单、支付订单、订单出库这 3 个消息应该保证顺序性,如下图:
这一步先拉取rocketmqinc/rocketmq镜像,docker pull rocketmqinc/rocketmq
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://louluan.blog.csdn.net/article/details/91368332
一说到Android的消息机制,自然就会联想到Handler,我们知道Handler是Android消息机制的上层接口,因此我们在开发过程中也只需要和Handler交互即可,很多人认为Handler的作用就是更新UI,这也确实没错,但除了更新UI,Handler其实还有很多其他用途,比如我们需要在子线程进行耗时的I/O操作,可能是读取某些文件或者去访问网络等,当耗时操作完成后我们可能需要在UI上做出相应的改变,但由于Android系统的限制,我们是不能在子线程更新UI控件的,否则就会报异常,这个时候Handler就可以派上用场了,我们可以通过Handler切换到主线程中执行UI更新操作。
Q :在线程中可以直接调用 Handler 无参的构造方法吗?在主线程和子线程中有没有区别? A:在主线程中可以;在子线程中会抛出RuntimeException, 需要先调用 Looper.prepare()。主线程在启动的时候已经在调用过Looper.prepare()。
rocketmq-client-4.5.2-sources.jar!/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java
rocketmq-spring-boot-2.0.4-sources.jar!/org/apache/rocketmq/spring/annotation/ConsumeMode.java
参考:https://mp.weixin.qq.com/s/AvpOq6eh-IBDJj2SXa_wXw https://www.jianshu.com/p/25a05bf42e05
hello,小伙伴们,王子又来和大家研究RocketMQ的原理了,之前的文章RocketMQ生产部署架构如何设计中,我们已经简单的聊过了生产者是如何发送消息给Broker的。
我们知道在编程时许多操作(如更新UI)需要在主线程中完成,而且,耗时操作(如网络连接)需要放在子线程中,否则会引起ANR。所以我们常使用Handler来实现线程间的消息传递,这里讨论的也就是Handler的运行机制。
rocketmq-client-go-v2.0.0/consumer/strategy.go
Handler中的消息队列如上图所示,是一个单链表,各个消息按照执行时间先后排列,消息类型分为三种:普通消息(normal)、屏障消息(barrier)、异步消息(async)。
1、定义:Android的消息机制主要是指Handler的运行机制,Handler并不是专门用于更新UI的,它只是常被开发者用来更新UI,是同一个进程中线程间的通信机制,能够将一个任务切换到指定的线程中去执行。
rocketmq-client-go的api.go定义了Producer、TransactionProducer、PushConsumer、PullConsumer,其中PullConsumer目前还没有实现
Cheddar/cheddar/cheddar-messaging/src/main/java/com/clicktravel/cheddar/infrastructure/messaging/MessageSender.java
线程启动之后,进入main()方法,在main()方法中进行线程的一些初始化,初始化工作完成之后,会调用Looper.loop()进行消息监听,而loop()方法是一个死循环,从而保证线程不会立即退出:
在Android Handler机制6之MessageQueue简介中的五、native层代码的初始化中 说了MessaegQueue构造函数调用了nativeInit(),为了更好的理解,我们便从MessageQueue构造函数开始说起
在深入解析Android中Handler消息机制一文中,我们学习了Handler消息机制的java层代码,这次我们来学习Handler消息机制的native层代码。
书接上文,在分析 Toast 源码的过程中我们涉及到了 Handler,这个在 Android 开发里经常用到的类——线程切换、顺序执行、延时执行等等逻辑里往往少不了它的身影,跟它一起搭配使用的通常是 Runnable 和 Message,还有它身后的好基友 Looper 与 MessageQueue。Runnable 相信大家都很熟悉了,本文的主角就是标题里的三剑客——Handler、Looper 和 MessageQueue,当然少不了说到 Message。
最近在查看应用的线上日志统计时,发现一个 MessageQueue.nativePollOnce() 的记录,具体信息如下:
功能一 : 发送消息到 Looper 中的 消息队列 MessageQueue 中 ;
rocketmq-client-go-v2.0.0/producer/selector.go
本文主要研究一下rocketmq的ConsumeMode.CONCURRENTLY
生产者 producer 在发送消息的时候,每个消息发送到 broker 只存储在某一个 quene 上。那么 producer 是怎么选择 queue 呢?
不能,一个线程对应一个Looper对象,通过ThreadLocal保证一个线程只有一个Looper与之对应,如果多次调用Looper.prepare();则会抛出运行时异常。
① 子线程更新 UI : 在子线程中更新 UI , 就是在子线程中将刷新 UI 的任务分配给了主线程 ; ( 子线程刷新 UI 会崩溃 )
首先在理解生产者发消息之前,必须要明白一个概念:MessageQueue是什么? 其实MessageQueue是RocketMq的一种数据分片+物理存储机制。
在Android面试中,关于 Handler 的问题是必备的,但是这些关于 Handler 的知识点你都知道吗?
模仿 Android 中的 Message 基本功能 , 提供 what 与 obj 变量 , 提供一个回收方法 ;
Android 消息机制的主要是指的是 Handler 的运行机制以及 Handler 所附带的 MessageQueue 和 Looper 的工作过程,这三者实际上是一个整体,只不过我们在开发过程中比较多地接触 Handler 而已。
io/openmessaging/rocketmq/consumer/PullConsumerImpl.java
大家好,今天我为大家讲解一下Android系统下的Handler机制。做过Android系统开发的人都清楚,App应用程序的主线程是决对不能被阻塞的,因为它的主线程就是UI线程。一旦它被阻塞了,用户会感觉APP卡死似的,基本就没法使用了。所以在音视频直播项目中,我们对摄像头的控制,视频画面的渲染都要放在子线程中进行。下面我们就来详细的剖析一下Android系统下的Handler和HandlerThread机制。
Handler封装了消息的发送,也负责接收消。通过post方法和sendMessage发送消息。内部会跟Looper关联。
Android Handler我们都很熟,也经常也用它,一般可以用Handler发送一个消息Message,或者Post一个Runnable对象,而且都可以给它们加上延时,如果操作的Handler对象是在onCreate方法中初始化的,那么handleMessage回调和Runnable对象的执行都运行在UI线程,所以Handler就成为我们在工作线程刷新UI对象的一个媒介。那么对于这个我们日常工作中经常使用的小伙伴,好奇心驱使,我们希望对它了解更多。
领取专属 10元无门槛券
手把手带您无忧上云