喝水小助手实现思路附代码案例
点击▲关注 “爪哇笔记” 给公众号标星置顶
更多精彩 第一时间直达
大家好,我是本群的提醒喝水小助手,这是今天的第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之后给用户发送短信通知,限时支付、缓存系统、红包过期、开奖提醒等等。
小结
以上方案为单机模式,生产环境可根据实际业务需求选择使用。
喝水小助手实现思路附代码案例相关推荐
- Python-提醒喝水小助手
想法 坐在电脑前坐久了常常忘了要站起来活动活动,用现有的程序又太笨重,于是写了个脚本通知自己. 功能 每隔30min通知自己起身活动 开机问候且自启动 实现 需要安装win10toast库 pip i ...
- C#射击类小游戏简单思路及代码
博主想做一个小时候玩的FC坦克大战的游戏,然后先写点简单的来整理一下设计思路.然后今天就写了一个非常简单的游戏框架,300行左右代码,最简单的功能可以实现.源码可以在博主的资源页下载 https:// ...
- QQ宠物吹泡泡游戏小助手 VC++6.0代码分析
最近玩QQ宠物,他总是心情低落,让我很不爽,让他玩耍吧,还得自己点鼠标,所以想偷个懒,试试能不能编个程序让电脑帮我做这个事情. 要干这件事就得先找一个游戏开刀,刚开始我找的是弹力球游戏,不就是点鼠标么 ...
- 2022年第十四届华中杯数学建模A题解题思路附代码
A 题 分拣系统优化问题 某电商公司配送中心的工作流程分为统计汇总.转运上架.按订单分拣.核对打包等 步骤.其中,分拣环节操作复杂,耗时较长,其效率是影响配送中心整体性能的关键因素. ...
- 用最普通的文档,我做了一个小助手,没有一行代码
当我写下第一行文字时,雅格布就这样诞生了. 我的助手雅格布 雅格布是我的助手,它能在工作中,帮我做出正确的选择: 还能让我在工作中持续投入时间,并保持激情. 简单来说,雅格布是一个决策工具,专门解决选 ...
- 应用8255A控制LED小灯开闭(附代码注释)
设8255A的A口和B口都工作在方式0,A口作为输出口,接有8个开关;B口为输出口,接有8个发光二极管.系统硬件电路中不断扫描开关Ki,当K0闭合时,点亮LED0,LED2,LED4,LED6,其他L ...
- 基于遗传算法的多目标优化算法(附代码案例)
一.理论基础 多目标优化问题可以描述如下: 其中,f(x) 为待优化的目标函数:x 为 待优化的变量:lb 和 ub 分别为变量 x 的下限和上限约束:Aeq * x = beq 为变量 x 的线性等 ...
- 七、C/C++指针(易懂易学习,附代码案例)
七.C/C++指针 7.1 概述 7.1.1 内存 7.1.2 物理存储器和存储地址空间 7.1.3 内存地址 7.1.4 指针和指针变量 7.2 指针基础知识 7.2.1 指针变量的定义和使用 7. ...
- 十、文件操作(易懂易学习,附代码案例)
十.文件操作 10.1 概述 10.1.1 文件分类 10.1.2 磁盘文件的分类 10.2 文件的打开和关闭 10.2.1 文件指针FILE 10.2.2 文件的打开 10.2.3 文件的关闭 10 ...
最新文章
- 关键词排名下降怎么办-优八学院给你支招
- 【实习】京东搜索相关性算法部门
- aspx 与 ashx cs
- mysql栈空间大小_jvm 堆内存 栈内存 大小设置
- 输出字母沙漏+对称字符串
- 一个小技巧助您减少if语句的状态判断
- JAVA设计模式之3-抽象工厂模式
- USGS下载LANDSAT5 2级别 影像问题
- Web--用户注册界面
- Springboot毕设项目电子银行业务办理系统38kny(java+VUE+Mybatis+Maven+Mysql)
- RefineNet 理解
- matlab 绘图与动画制作
- 「万达董事会大换血」背后 | 一点财经
- 零知识证明之什么是QAP?什么是P/NP、NP完全问题(NPC问题)、NP hard问题?多项式时间
- linux上读取不到库文件,linux中make找不到库文件-lmpi的问题
- C语言编程之错误一:error C2059:syntax error : ‘)’
- Android自带人脸识别
- 华硕主板power supply surges detected during the previons power on 问题解决
- 【五子棋AI循序渐进】发布一个完整的有一定棋力的版本(含源码)
- 全志h2参数_全志h3芯片性能及参数评测