开始看AMQConnection源码,这个也是一个比较大的类,首先我需要扫描相关的类,就是这个类相关成员变量,这篇主要解决HeartbeatSender, 看类名就知道是心跳发送类,具体看一下有什么方法和值得学习的地方
-
它是为一个AMQConnection管理和发送心跳检测,它线程独立于Connection工作线程,两者互不干扰
-
它是一个final类
1、 成员变量和常量
变量名和常量名 | 默认值 | 描述 |
---|---|---|
final Object monitor | new Object() | 同步锁对象 |
final FrameHandler frameHandler | Frame处理器,详情参考源码分析 | |
final ThreadFactory threadFactory | 线程工作类 | |
ScheduledExecutorService executor | 周期执行(心跳任务) | |
final boolean privateExecutor | 这个该类默认创建关闭时候也自动销毁,外部创建Executor不需要管 | |
ScheduledFuture<?> future | 周期返回值 | |
boolean shutdown | false | 标记是否关闭 |
volatile long lastActivityTime | 最后一次活跃时间 |
- shutdown 成员变量为啥不加volatile关键字呢? 其实它在monitor锁下运行了,不存在多线程情况,而lastActivityTime是存在的
2、方法
方法名 | 描述 | 图示 |
---|---|---|
HeaderbeatSender(frameHandler, privateExecutor, executor, threadFactory) | 构造方法 | |
void signalActivity() | 当前活动时间(发送Frame最近一次) | |
void setHeartbeat(int heartbeatSeconds) | 设置心跳周期任务 | 1 |
void shutdown() | 关闭操作 | 2 |
2.1、图示
- void setHeartbeat(int heartbeatSeconds)
- 总结
- 判断当前通道状态是关闭吗?如果关闭没有必要执行心跳任务了
- 判断future是否为空,也就说明原来是否有心跳任务在跑,有则需要取消历史任务
- 是否需要创建线程执行器,单个线程执行器
- 它是设置心跳一半触发发送心跳检测,本来60秒触发一次,现在就30秒触发一次, 防止最近活动时间在心跳后面,也就能够正常传输数据,也就说明心跳正常了,只有最近活动时间和心跳间隔一半 小于当前时间,说明需要发心跳检测了,且心跳检测是在0号通道上
- 执行周期任务心跳任务
- void shutdown()
- 总结
- 1.有一个疑问,为啥要做锁外关闭执行器呢,锁内为啥不行,难道执行shutdown可能导致死锁什么的?
3、总结
- 了解心跳定时周期任务
- 心跳默认通道是0
- 有个问题点就是为线程执行器需要到锁外执行关闭操作