点击▲关注 “爪哇笔记”   给公众号标星置顶

更多精彩 第一时间直达

大家好,我是本群的提醒喝水小助手,这是今天的第X轮。希望此刻看到消息的人可以和我一起来一杯水。一小时后的我继续提醒大家喝水。和我一起成为一天八杯水的人吧!

最初是为了提醒大家注意身体健康,也有提醒运动、提醒站立等等,后来大家脑洞大开的创作出了各种滑稽搞笑的表情包,例如提醒喝可乐,提醒上厕所等等,该表情包也开始在不同的圈子里流行起来,例如在游戏里有提醒开黑,在B站有提醒更新视频等等。

定时任务

利用SpringTask、Quartz实现定时提醒发送,不过小程序的消息模板推送已经不支持随意给用户发消息了,需要用户自行去触发。

延迟队列

用户手动触发一次喝水动作,这时候我们可以使用延迟队列来实现,推荐使用开源的第三方工具包redisson,同时保证redis支持lua特性。

配置application.properties

# redisson lock
redisson.address=redis://127.0.0.1:6379
redisson.password=123456

参数配置类RedissonProperties 

@Data
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {private int timeout = 3000;private String address;private String password;private int connectionPoolSize = 64;private int connectionMinimumIdleSize=10;private int slaveConnectionPoolSize = 250;private int masterConnectionPoolSize = 250;private String[] sentinelAddresses;private String masterName;
}

自动装配 RedissonAutoConfiguration

@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {@Autowiredprivate RedissonProperties redssionProperties;/*** 单机模式自动装配* @return*/@BeanRedissonClient redissonSingle() {Config config = new Config();SingleServerConfig serverConfig = config.useSingleServer().setAddress(redssionProperties.getAddress).setTimeout(redssionProperties.getTimeout()).setConnectionPoolSize(redssionProperties.getConnectionPoolSize()).setConnectionMinimumIdleSize(redssionProperties.getConnectionMinimumIdleSize());if(StringUtils.isNotBlank(redssionProperties.getPassword())) {serverConfig.setPassword(redssionProperties.getPassword());}return Redisson.create(config);}/*** 装配locker类,并将实例注入到RedissLockUtil中* @return*/@BeanRedissLockUtil redissLockUtil(RedissonClient redissonClient) {RedissLockUtil redissLockUtil = new RedissLockUtil();redissLockUtil.setRedissonClient(redissonClient);return redissLockUtil;}
}

工具类RedissLockUtil

/*** redis分布式锁帮助类* @author 爪哇笔记 By https://blog.52itstyle.vip*/
public class RedissLockUtil {private static RedissonClient redissonClient;public void setRedissonClient(RedissonClient locker) {redissonClient = locker;}/*** 初始红包数量* @param key* @param count*/public void initCount(String key,int count) {RMapCache<String, Integer> mapCache = redissonClient.getMapCache("skill");mapCache.putIfAbsent(key,count,3,TimeUnit.DAYS);}/*** 递增* @param key* @param delta 要增加几(大于0)* @return*/public int incr(String key, int delta) {RMapCache<String, Integer> mapCache = redissonClient.getMapCache("skill");if (delta < 0) {throw new RuntimeException("递增因子必须大于0");}return  mapCache.addAndGet(key, 1);//加1并获取计算后的值}/*** 递减* @param key 键* @param delta 要减少几(小于0)* @return*/public int decr(String key, int delta) {RMapCache<String, Integer> mapCache = redissonClient.getMapCache("skill");if (delta < 0) {throw new RuntimeException("递减因子必须大于0");}return mapCache.addAndGet(key, -delta);//加1并获取计算后的值}public static RedissonClient getRedissonClient() {return redissonClient;}
}

入队列,伪代码:

RedissonClient redissonClient = RedissLockUtil.getRedissonClient();
/**
* 目标队列
*/
RBlockingQueue<RemindDelay> blockingRemindQueue
= redissonClient.getBlockingQueue("remindDelayQueue");
/**
* 定时任务将到期的元素转移到目标队列
*/
RDelayedQueue<RemindDelay> delayedRemindQueue
= redissonClient.getDelayedQueue(blockingRemindQueue);
/**
* 延时信息入队列
*/
delayedRemindQueue.offer(new RemindDelay(remind.getId()), sec, TimeUnit.SECONDS);

队列消息实体标识:

public class RemindDelay implements Serializable {/*** 主键ID*/private  long id;/*** 创建时间戳*/private  long timestamp;public RemindDelay() {}public RemindDelay(long id) {this.id = id;this.timestamp = System.currentTimeMillis();}public long getId() {return id;}public long getTimestamp() {return timestamp;}
}

消费提醒队列:

/*** 消费提醒队列*/
@Component
public class RemindRunner implements ApplicationRunner {private final static Logger LOGGER = LoggerFactory.getLogger(RemindRunner.class);private static int corePoolSize = Runtime.getRuntime().availableProcessors();private static ThreadPoolExecutor executor  =new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10L, TimeUnit.SECONDS,new LinkedBlockingQueue<>(100));@Autowiredprivate RemindService remindService;@Autowiredprivate WxMaService wxService;@Overridepublic void run(ApplicationArguments args) throws Exception {/*** 出队列*/RedissonClient redissonClient = RedissLockUtil.getRedissonClient();RBlockingQueue<RemindDelay> delayedRemindQueue= redissonClient.getBlockingQueue("remindDelayQueue");new Thread(() -> {LOGGER.info("提醒队列启动成功");while (true){try {RemindDelay delay = delayedRemindQueue.take();push(delay);LOGGER.info("提醒ID:{}",delay.getId());} catch (InterruptedException e) {e.printStackTrace();}}}).start();}public void push(RemindDelay delay){/*** 推送*/Runnable task = () -> {//发送消息通知逻辑};executor.execute(task);}
}

适用场景

淘宝订单到期,下单成功后60s之后给用户发送短信通知,限时支付、缓存系统、红包过期、开奖提醒等等。

小结

以上方案为单机模式,生产环境可根据实际业务需求选择使用。

喝水小助手实现思路附代码案例相关推荐

  1. Python-提醒喝水小助手

    想法 坐在电脑前坐久了常常忘了要站起来活动活动,用现有的程序又太笨重,于是写了个脚本通知自己. 功能 每隔30min通知自己起身活动 开机问候且自启动 实现 需要安装win10toast库 pip i ...

  2. C#射击类小游戏简单思路及代码

    博主想做一个小时候玩的FC坦克大战的游戏,然后先写点简单的来整理一下设计思路.然后今天就写了一个非常简单的游戏框架,300行左右代码,最简单的功能可以实现.源码可以在博主的资源页下载 https:// ...

  3. QQ宠物吹泡泡游戏小助手 VC++6.0代码分析

    最近玩QQ宠物,他总是心情低落,让我很不爽,让他玩耍吧,还得自己点鼠标,所以想偷个懒,试试能不能编个程序让电脑帮我做这个事情. 要干这件事就得先找一个游戏开刀,刚开始我找的是弹力球游戏,不就是点鼠标么 ...

  4. 2022年第十四届华中杯数学建模A题解题思路附代码

    A 题 分拣系统优化问题         某电商公司配送中心的工作流程分为统计汇总.转运上架.按订单分拣.核对打包等 步骤.其中,分拣环节操作复杂,耗时较长,其效率是影响配送中心整体性能的关键因素. ...

  5. 用最普通的文档,我做了一个小助手,没有一行代码

    当我写下第一行文字时,雅格布就这样诞生了. 我的助手雅格布 雅格布是我的助手,它能在工作中,帮我做出正确的选择: 还能让我在工作中持续投入时间,并保持激情. 简单来说,雅格布是一个决策工具,专门解决选 ...

  6. 应用8255A控制LED小灯开闭(附代码注释)

    设8255A的A口和B口都工作在方式0,A口作为输出口,接有8个开关;B口为输出口,接有8个发光二极管.系统硬件电路中不断扫描开关Ki,当K0闭合时,点亮LED0,LED2,LED4,LED6,其他L ...

  7. 基于遗传算法的多目标优化算法(附代码案例)

    一.理论基础 多目标优化问题可以描述如下: 其中,f(x) 为待优化的目标函数:x 为 待优化的变量:lb 和 ub 分别为变量 x 的下限和上限约束:Aeq * x = beq 为变量 x 的线性等 ...

  8. 七、C/C++指针(易懂易学习,附代码案例)

    七.C/C++指针 7.1 概述 7.1.1 内存 7.1.2 物理存储器和存储地址空间 7.1.3 内存地址 7.1.4 指针和指针变量 7.2 指针基础知识 7.2.1 指针变量的定义和使用 7. ...

  9. 十、文件操作(易懂易学习,附代码案例)

    十.文件操作 10.1 概述 10.1.1 文件分类 10.1.2 磁盘文件的分类 10.2 文件的打开和关闭 10.2.1 文件指针FILE 10.2.2 文件的打开 10.2.3 文件的关闭 10 ...

最新文章

  1. 关键词排名下降怎么办-优八学院给你支招
  2. 【实习】京东搜索相关性算法部门
  3. aspx 与 ashx cs
  4. mysql栈空间大小_jvm 堆内存 栈内存 大小设置
  5. 输出字母沙漏+对称字符串
  6. 一个小技巧助您减少if语句的状态判断
  7. JAVA设计模式之3-抽象工厂模式
  8. USGS下载LANDSAT5 2级别 影像问题
  9. Web--用户注册界面
  10. Springboot毕设项目电子银行业务办理系统38kny(java+VUE+Mybatis+Maven+Mysql)
  11. RefineNet 理解
  12. matlab 绘图与动画制作
  13. 「万达董事会大换血」背后 | 一点财经
  14. 零知识证明之什么是QAP?什么是P/NP、NP完全问题(NPC问题)、NP hard问题?多项式时间
  15. linux上读取不到库文件,linux中make找不到库文件-lmpi的问题
  16. C语言编程之错误一:error C2059:syntax error : ‘)’
  17. Android自带人脸识别
  18. 华硕主板power supply surges detected during the previons power on 问题解决
  19. 【五子棋AI循序渐进】发布一个完整的有一定棋力的版本(含源码)
  20. 全志h2参数_全志h3芯片性能及参数评测

热门文章

  1. 数论专题(1)数论函数,整数分块
  2. 一篇文章教会你利用Python网络爬虫获取电影天堂视频下载链接
  3. 处理程序 SafedogIISAuditor32 错误代码 0x80070003
  4. Linux virtual filesystem switch I 磁盘相关概念以及知识
  5. 条件断点、条件记录断点
  6. UE4蓝图基础——蓝图实现物体移动和物体旋转
  7. plc转单片机,永久使用
  8. Requests 与 BeautifulSoup 模块
  9. js 使用console计算代码运行时间
  10. 免费PPT模板,应有尽有