当前位置: 首页 > 编程日记 > 正文

java redis管理_优雅时间管理Java轻松做到,想学么?

原标题:优雅时间管理Java轻松做到,想学么?

来源 |http://rrd.me/gCQHp

前言:需求是这样的,在与第三方对接过程中,对方提供了token进行时效性验证,过一段时间token就会失效.后台有定时任务在获取,但是偶尔会出现token失效,这是因为在获取的时候,定时任务正在跑,可能正在获取最新的token中,这个时候如何过一段时间(比如800毫秒之后)再请求呢?小王仰望天空45度,思考起来了。。。

一:时间控制的几种方案

1.1: 从线程方面解决

最简单粗暴的一种实现方案:Thread.sleep(800),但是很快就被小王给pass掉了。为什么呢?虽然这种方式可以,但是存在一个隐患,如果在多线程环境下,线程很容易被interrupt,这样代码就会抛出异常,这样线程就会挂起,导致整个线程异常结束。实在是不够优雅,违背了我们设计的初衷。

1.2:使用Timer

查阅了jdk,我发现有个实现定时的类,使用它是可以的,在jdk中提供了定时器类,这个类的主要作用就是控制一定的时间来简单的定时执行某个任务。有点简单的elasticJob的设计味道。接下来看一下,用timmer如何实现延时。。有点惊喜,我们来写一个最简单的例子来看一下如何实现定时任务:

publicclassTimmerTest{

/**

* 测试方法

*/

publicvoidtest{

Timer timer = newTimer;

timer.schedule( newMyTask, 800);

}

publicclassMyTaskextendsTimerTask{

/**

* 运行方法

*/

@Override

publicvoidrun{

System.out.println( "输出");

}

}

}

这是一个很简单的定时器实现,可以看出它只需要将方法对应的类继承自MyTask就可以实现定时执行,这种方法是可以实现延时的效果,但是它有一个致命的缺点:对代码的侵入性太大,为了实现定时我们不得已将对应的方法封装成一个类,然后放在定时器里执行。这样的、是可以的,但未免也有点太得不偿失了。为此我要更改整个类的结构,对于修改一个东西,我们要尽量按照最简单的方式最好的效果来实现,所以这种方案也应该pass掉。

1.3:redis延时

在redis中存在一个命令:EXPIRE,这个命令可以设置键存活的时间。一旦超过指定的时间,redis就会将键对应的值给删除掉,因此可以利用这一特性,我们来曲线实现延时功能。在redis的实际命令如下:

ba1f8055a94b7cf571d23cc6b71ba02c.png

通过EXPIRE命令可以设置键的过期时间,一旦超过预设的时间,值就会变成(nil)。利用这一点,加入一些业务参数,我们就可以有效的实现延时的目的。通过redis的过期时间使用redis的好处有以下几点:

1:对代码的侵入性低,不用额外起另外的线程来执行。只需要加入一个方法就可以对单流程的时间控制

2:实现方便灵活,通过key设值可以加入一些唯一性的id来表示业务含义,从而保证业务的稳健实现

3:简单,真正的代码实现起来只有很少,下面会给出代码示范。

二:redis

2.1:maven中引入redis

引入spring-boot-starter-data-redis,这是springboot专门针对redis出的整合依赖库,整合度要比jedis、和redssion都要好,所以推荐这个依赖库:

< dependency>

< groupId>org.springframework.boot groupId>

< artifactId>spring-boot-starter-data-redis artifactId>

< exclusions>

< exclusion>

< groupId>io.lettuce groupId>

< artifactId>lettuce-core artifactId>

exclusion>

exclusions>

dependency>

< dependency>

< groupId>redis.clients groupId>

< artifactId>jedis artifactId>

dependency>

2.2: 在springboot中配置redis

importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.context.annotation.Bean;

importorg.springframework.context.annotation.Configuration;

importorg.springframework.data.redis.core.RedisTemplate;

importorg.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;

importorg.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration

publicclassRedisConfig{

@Autowired

privateRedisTemplate redisTemplate;

/**

* redisTemplate实例化

*

* @return

*/

@Bean

publicRedisTemplate redisTemplateInit{

//设置序列化Key的实例化对象

redisTemplate.setKeySerializer( newStringRedisSerializer);

//设置序列化Value的实例化对象

redisTemplate.setValueSerializer( newGenericJackson2JsonRedisSerializer);

returnredisTemplate;

}

}

2.2:redisTemplate模板工具类

@Component

publicclassRedisManager{

privatestaticfinalLogger LOGGER = LoggerFactory.getLogger(RedisManager.class);

@Autowired

privateRedisTemplate redisTemplate;

/**

* 设置对象

*

* @paramkey key

* @paramvalue value值

* @param 返回值泛型

* @return正确的值: 错误的值:null

*/

@SuppressWarnings( "unchecked")

public ValueOperations setObject( finalString key, finalT value){

finalValueOperations operation = redisTemplate.opsForValue;

operation.set(key, value);

returnoperation;

}

/**

* 设置对象及失效时间 (单位:秒)

*

* @paramkey key

* @paramvalue value值

* @param 返回值泛型

* @paramtime 秒值

* @return正确的值: 错误的值:null

*/

@SuppressWarnings( "unchecked")

public ValueOperations setObject( finalString key, finalT value, finallongtime){

finalValueOperations operation = redisTemplate.opsForValue;

operation.set(key, value, time, TimeUnit.SECONDS);

returnoperation;

}

/**

* 设置对象及失效时间(单位:毫秒)

*

* @paramkey key

* @paramvalue value值

* @param 返回值泛型

* @paramtime 秒值

* @return正确的值: 错误的值:null

*/

@SuppressWarnings( "unchecked")

public ValueOperations setObjectForMillSeconds( finalString key, finalT value, finallongtime){

finalValueOperations operation = redisTemplate.opsForValue;

operation.set(key, value, time, TimeUnit.MILLISECONDS);

returnoperation;

}

/**

* 获取对象

*

* @paramkey 键

* @return正确的值:Object值对象

* 错误的值:null

*/

@SuppressWarnings( "unchecked")

publicObject getObject( finalString key){

finalValueOperations valueOperations = redisTemplate.opsForValue;

if(valueOperations == null|| !redisTemplate.hasKey(key)) {

returnnull;

}

finalObject object = valueOperations.get(key);

returnobject;

}

/**

* 从缓存中获取string值

*

* @paramkey

* @return*/

@SuppressWarnings( "unchecked")

publicString getString( finalString key){

String value = "";

finalValueOperations valueOperations = redisTemplate.opsForValue;

if(valueOperations != null&& redisTemplate.hasKey(key)) {

finalObject object = valueOperations.get(key);

if( null!= object) {

LOGGER.info( "--getString--object not empty");

value = object.toString;

} else{

LOGGER.info( "--getString--object empty");

}

}

returnvalue;

}

2.2:在redis中实现时间控制

2.2.1:在流程中停留一段时间,通过无限循环来不断的从redis取数值,一旦取到的值为null(redis的键值为null)就退出,这样的写法有点类似于以前CAS的些许味道,通过无限循环比较值。

importcom.youjia.orders.redis.RedisManager;

importorg.junit.Test;

importorg.springframework.beans.factory.annotation.Autowired;

importjava.util.Objects;

/**

* @Auther: Yrion

* @Date: 2019-01-11 23:36

*/

publicclassRedisTestextendsOrderProviderApplicationTests{

@Autowired

privateRedisManager redisManager;

@Test

publicvoidtest{

controlTime( "10000001", 10L);

}

publicvoidcontrolTime(String requestId, Long timeOut){

if(Objects.isNull(requestId) || Objects.isNull(timeOut)) {

return;

}

//something code

finalString value = "value";

redisManager.setObject(requestId, value, timeOut);

finallongstartTime = System.currentTimeMillis;

System.out.println( "开始控制时间");

//start

for(; ; ) {

if(Objects.isNull(redisManager.getObject(requestId))) {

break;

}

}

finallongendTime = System.currentTimeMillis;

finallonguseTime = endTime - startTime;

System.out.println( "一共耗费时间:"+ useTime);

}

}

outPut:

开始控制时间

一共耗费时间:10042

三:总结

本篇博文讲述了在平时工作中,我们可能会遇到的一些关于时间控制的问题,在这个问题上我又进行了进一步的探讨,如何实现优雅的解决问题?我们解决问题不仅仅是要把这个问题解决了,而是要考虑如何更好更秒的解决,这就要善于利用一些中间件或者工具类提供的功能特性,善于发现、及时变通,把这种特性利用到我们的代码中,会对我们的开发起到推波助澜、如虎添翼的作用!返回搜狐,查看更多

责任编辑:

相关文章:

jenkins运行日志时间与linux,Jenkins 用户文档(运行多个步骤)

运行多个步骤管道由多个步骤组成&#xff0c;允许你构建、测试和部署应用程序&#xff0c;Jenkins管道允许你以简单的方式组成多个步骤&#xff0c;可以帮助你为任何类型的自动化过程建模。将“步骤”想象成执行单个操作的单个命令&#xff0c;当一个步骤成功时&#xff0c;它将…

HPU组队赛B:问题(二进制枚举)

时间限制1 Second 内存限制 512 Mb 题目描述 你有n个问题&#xff0c;你已经估计了第i个问题的难度为Ci,现在你想使用这些问题去构造一个问题集。比赛的问题集必须包含至少两个问题&#xff0c;而且比赛的总难度必须至少为l至多为r,此外最简单的问题和最难的问题之间的差异至少…

html脱机不显示图片,Python绘图脱机图表嵌入HTML(不工作)

aPlot是绘图文件的文件名。在在您的iframe中&#xff0c;您将.embed?width800&height550添加到文件名中&#xff0c;这将导致一个不存在的文件名。在当您删除这个字符串时&#xff0c;即src" aPlot "&#xff0c;它应该可以工作。在不必嵌入整个HTML文件&…

数据库分库分表(sharding)系列

数据库分库分表(sharding)系列转载于:https://www.cnblogs.com/gotodsp/p/6517478.html

php imagecopy 用法,php使用imagecopymerge()函数创建半透明水印

使用imagecopymerge() 函数创建半透明水印&#xff0c;供大家参考&#xff0c;具体内容如下// 加载要加水印的图像$im imagecreatefromjpeg(photo.jpeg);// 首先我们从 GD 手动创建水印图像$stamp imagecreatetruecolor(100, 70);imagefilledrectangle($stamp, 0, 0, 99, 69,…

linux系统yum源,Linux开启安装EPEL YUM源

我们用yum安装软件时,经常发现我们的yum源里面没有该软件&#xff0c;需要自己去wget&#xff0c;然后configure,make,make install&#xff0c;太折腾了。其实&#xff0c;CentOS还有一个源叫做 EPEL (Extra Packages for Enterprise)&#xff0c;里面有1万多个软件&#xff0…

MATLAB简易验证码识别程序介绍

本推文主要识别的验证码是这种:第一步: 二值化所谓二值化就是把不需要的信息通通去除&#xff0c;比如背景&#xff0c;干扰线&#xff0c;干扰像素等等&#xff0c;只剩下需要识别的文字&#xff0c;让图片变成2进制点阵。第二步: 文字分割为了能识别出字符&#xff0c;需要对…

mac终端命令-----常规操作

OSX 的文件系统 OSX 采用的Unix文件系统&#xff0c;所有文件都挂在跟目录 / 下面&#xff0c;所以不在要有Windows 下的盘符概念。 你在桌面上看到的硬盘都挂在 /Volumes 下。 比如接上个叫做 USBHD的移动硬盘&#xff0c;桌面上会显示出一个硬盘图标&#xff0c;它实际在哪里…

php true true true,php-为什么此评估为true

标签&#xff1a;php乳清这算是真的吗&#xff1f;$val20;//outputs that is an error123if($val2error123){echo that is an error123;}else{echo that is not an error123;}解决方法:您正在将字符串与整数进行比较.为了进行比较,首先将字符串转换为整数.当“ error123”转换为…

一个html文件放到服务器访问,访问云服务器里面的html文件

弹性云服务器 ECS弹性云服务器(Elastic Cloud Server)是一种可随时自助获取、可弹性伸缩的云服务器&#xff0c;帮助用户打造可靠、安全、灵活、高效的应用环境&#xff0c;确保服务持久稳定运行&#xff0c;提升运维效率三年低至5折&#xff0c;多种配置可选了解详情建站入门|…

limbo可以运行linux,这次真的了,安卓手机可以安装 Windows 10 了

原标题&#xff1a;这次真的了&#xff0c;安卓手机可以安装 Windows 10 了上回雷锋哥给大家分享过「安卓可以体验 "Windows 10" 了」实际上就是一个第三方安卓桌面启动器模仿 Windows 10 的主题&#xff0c;所以只能说是美化&#xff0c;并非真的运行 Windows 10 系…

Fedora dnf配置

1、在配置文件/etc/dnf/dnf.conf中加入&#xff1a; fastestmirrortruekeepcachetrue这样下载安装软件就快多了。 2、dnf常用命令 检查并升级可用软件包&#xff1a;$ dnf update删除缓存:$dnf clean all列出可用的软件源&#xff1a;$ dnf repolist搜索软件:$ dnf search $…

2021梧州一中高考成绩查询,2021年广西高考成绩查询网站查分网址:https://www.gxeea.cn/...

【摘要】高考结束后大家最为关心的问题就是在哪里查分&#xff0c;如何查分&#xff0c;高考频道特别整理2021年广西高考成绩查询查分网址&#xff0c;成绩公布时考生可直接点击网址进行查分&#xff0c;预祝大家都能顺利的考上理想的大学&#xff01;由于&#xff0c;各省级招…

php ip地址地区,PHP查询ip所在地(省份,市)

通过IP获取归属地图1 &#xff1a; 返回数据图2 &#xff1a; 查询成功如果喜欢的话&#xff0c;可以试试&#xff0c;几行代码就能搞定&#xff0c;我觉得还是挺实用的&#xff01;&#xff01;

描述一下 Intent 和 IntentFilter?

Android 中通过 Intent 对象来表示一条消息&#xff0c;一个 Intent 对象不仅包含有这个消息的目的地&#xff0c;还可以包含消息的内容&#xff0c;这好比一封 Email&#xff0c;其中不仅应该包含收件地址&#xff0c;还可以包含具体的内容。对于一个 Intent 对象&#xff0c;…

linux字符界面教程,打造字符界面的多媒体Linux系统

打造字符界面的多媒体Linux系统打造字符界面的多媒体Linux系统0 环境与目标硬件&#xff1a;ThinkPad R52笔记本一台。目标&#xff1a;字符界面的LINUX系统&#xff0c;同时可以看图片&#xff0c;听音乐&#xff0c;看视频&#xff0c;无线上网。1 系统安装1.1 最小安装系统官…

Linux 环境 搭建Git 服务器,并且修改SSH端口使用

1.环境配置说明 服务器 CentOS 7 git&#xff08;git version 1.8.3.1&#xff09; 客户端 Windows10 SourceTree 2.安装 Git 服务器端安装&#xff1a; sudo yum -y install git 查看安装版本 #git --version git version 1.8.3.1 客户端安装 下载 SourceTree for Window 下…

php发光字体代码,CSS3怎么实现字体发光效果

这次给大家带来CSS3怎么实现字体发光效果&#xff0c;CSS3实现字体发光效果的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。博客页面左上角的“猿来是勇者”文字已制作发光效果&#xff0c;分享方法如下:该属性为文本添加阴影效果text-shadow:h-shado…

计算机专业英语chapter012,计算机专业英语 chapter_1.ppt

计算机专业英语 chapter_1Chapter 1 Information Technology, The Internet, and You;Competencies;Competencies能力&#xff0c;要求After you have read this chapter, you should be able to: Explain the five parts of an information system: people, procedures, softw…

C#与C++的区别

1,C#不支持多重继承&#xff0c;这是与C明显区别的地方&#xff0c;说真的多重继承有时候用起来挺麻烦的&#xff0c;可能微软怕你用不好吧&#xff0c;不给你提供了&#xff0c;但我个人觉得没有了多重继承感觉有点可惜。 2.在标准的C#安全代码中不支持指针类型的操作&#xf…

黑裙安装linux环境,Linux学习笔记(一) ---- 安装Linux系统

学习Linux的第一件事情&#xff0c;你得先有个Linux系统&#xff0c;才能知道怎么学吧&#xff1f;于是安装Linux是第一部,找网上找了不少教程&#xff0c;自己总结了一下&#xff0c;些一个博文先。我安装的Linux是在VMWare 7.2版本上安装的&#xff0c;安装的是Ret Hat Linux…

mybatis批量更新的两种实现方式

mapper.xml文件&#xff0c;后台传入一个对象集合&#xff0c;另外如果是mysql数据库&#xff0c;一点在配置文件上加上&allowMultiQueriestrue&#xff0c;这样才可以执行多条sql&#xff0c;以下为mysql&#xff1a; <update id"batchUpdate" parameterType…

php常用20函数,PHP常用函数

//PHP设置跨域header("Access-Control-Allow-Origin:*");//PHP设置JSON头 以JSON格式输出header("Content-type:application/json; charsetutf-8");//正则取字符串preg_match_all(/字符串(.*?)字符串/i,$data,$out);// PHP把JSON对象转字符串不转码输出js…

tcpdump保存数据包

1、启动tcpdump tcpdump 2、查看网卡 tcpdump -D 3. 抓取报文后隔指定的时间保存一次 tcpdump -i eth3 -s0 -G 60 -Z root -w %Y_%m%d_%H%M_%S.pcap 这里解释下-G选项 后面接时间 单位为秒 本例中的时间为60秒 4. 抓取报文后达到指定的大小保存一次 tcpdump -i eth3 -s0 -C 1 -…

在线翻译系统属于计算机应用领域中,【单选题】网状物编织物和机件上的滚花部分,可以在轮廓线附件用( )线示意画出...

参考答案如下单选【简答题】我决定明天五点起床。(ことになる・ことにする)题网【单选题】法律的规定:邀请招标,应向()个以上具备承担招标项目能力,资信良好的特定法人发出投标邀请书。状物轮【单选题】描述液体运动的方法不包括( )。编织部分【单选题】Everyone _________ on …

linux进行主机发现,linux – 网络上所有计算机的主机名发现

SSH不关心是否给出了要连接的主机名或IP地址(当有特定于主机的配置时,不确定是否适用).大多数MPI实现也不关心,例如在Open MPI连接中,URI地址都是数字,因此具有IP的主机文件可以正常使用.另一方面,HTTP服务器关心的是虚拟主机事件,其中许多不同站点解析为相同的IP地址,但服务器…

Android5.0之CoordinatorLayout的使用

CoordinatorLayout&#xff0c;中文译作协调者布局&#xff0c;光听这名字你可能很难判断出协调者布局有什么特点&#xff0c;那么我们来看看下面一张图片&#xff1a; 由于CSDN对图片大小的要求&#xff0c;我只能录制一个快速播放的动画&#xff0c;请大家见谅。但是显示效果…

微信js sdk动态引用

一般情况下&#xff0c;微信的js-sdk只需要直接引用script即可 <script src"http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> 但是有的时候&#xff0c;当我们的网页访问的环境多样的时候&#xff0c;比如APP内部&#xff0c;手机浏览器时候&…

java qq协议 c#,C# WebQQ协议群发机器人(三)

在前两篇文章中我已经给了绝大部分的WEBQQ的操作在这篇文章中不在过多的说明做法有的时候需要自己添加一些功能呢 怎么做呢&#xff0c;我这里给出一个方法。在调试webqq机器人时 我用google浏览器 的F12开发者工具来捕捉网络包&#xff0c;webqq绝大多数都是GET请求 参数用来用…

矩阵计算在计算机科学中,开发者必读:计算机科学中的线性代数(附论文)

来源&#xff1a;机器之心作者&#xff1a;Petros Drineas、Michael W. Mahoney本文共3994字&#xff0c;建议阅读6分钟。本文为你分享一篇来自普渡大学与UC Berkeley两位教授的概述论文中的线性代数知识。矩阵计算在计算机科学中占有举足轻重的地位&#xff0c;是每个开发者都…