用到的jar包:

    <!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
</dependency> <!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.8.1</version>
</dependency>

测试代码:

package redis;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool; public class RedisThread { public static void main1(String[] args) {
for (int i = 0; i < 3; i++) {
// final int k = i;
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 10; j++) {
int k = j;
// 连接本地的 Redis 服务
// Jedis jedis = new Jedis("localhost");
// 创建连接池对象
JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);
// 从连接池中获取一个jedis对象
Jedis jedis = jedisPool.getResource();
// synchronized (RedisThread.class) {
String v = jedis.get("a" + k);
// if (v == null) {
if (!jedis.exists("a" + k)) {
jedis.set("a" + k, Thread.currentThread().getName());
jedis.expire("a" + k, 60);
System.out.println(System.currentTimeMillis() + "--" + Thread.currentThread().getName()
+ "--key:" + ("a" + k) + "不存在,设置值为: " + Thread.currentThread().getName());
try {
// Thread.sleep((long) (Math.random()*1000));
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "--key:" + ("a" + k) + "存在,值为: " + v);
}
// }
jedis.close();
}
}
}).start();
}
}
/* 不加锁的运行结果: 可以看到一个键比如 a0被赋值了很多次,说明有线程安全问题(原因是getKey 和 setKey 的方法不同步),
* 如果在单服务环境可以用synchronized来解决,但是如果分布式多节点服务,synchronized 就无效了
*
* 1556503338616--Thread-2--key:a0不存在,设置值为: Thread-2
* 1556503338616--Thread-1--key:a0不存在,设置值为: Thread-1
* 1556503338616--Thread-0--key:a0不存在,设置值为: Thread-0
* 1556503338622--Thread-2--key:a1不存在,设置值为: Thread-2 Thread-0--key:a1存在,值为:
* Thread-2 1556503338622--Thread-1--key:a1不存在,设置值为: Thread-1
* 1556503338627--Thread-2--key:a2不存在,设置值为: Thread-2
* 1556503338627--Thread-0--key:a2不存在,设置值为: Thread-0
* 1556503338628--Thread-1--key:a2不存在,设置值为: Thread-1
* 1556503338634--Thread-2--key:a3不存在,设置值为: Thread-2
* 1556503338634--Thread-0--key:a3不存在,设置值为: Thread-0
* 1556503338634--Thread-1--key:a3不存在,设置值为: Thread-1
* 1556503338644--Thread-2--key:a4不存在,设置值为: Thread-2
*/ public static void main(String[] args) {
//获取redisson
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379");
RedissonClient redisson = Redisson.create(config);
//获取锁
RLock lock = redisson.getLock("mylock"); for (int i = 0; i < 3; i++) {
// final int k = i;
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 10; j++) {
int k = j;
// 连接本地的 Redis 服务
// Jedis jedis = new Jedis("localhost");
// 创建连接池对象
JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);
try {
//加分布式锁
lock.lock();
// 从连接池中获取一个jedis对象
Jedis jedis = jedisPool.getResource();
if (!jedis.exists("a" + k)) {
jedis.set("a" + k, Thread.currentThread().getName());
jedis.expire("a" + k, 60);
System.out.println(System.currentTimeMillis() + "--" + Thread.currentThread().getName()
+ "--key:" + ("a" + k) + "不存在,设置值为: " + Thread.currentThread().getName());
try {
// Thread.sleep((long) (Math.random()*1000));
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName() + "--key:" + ("a" + k) + "存在,值为: "
+ jedis.get("a" + k));
}
jedis.close();
} finally {
//释放分布式锁
lock.unlock();
}
}
}
}).start();
}
} /* 加上分布式锁后的运行结果: 可以看到每一个键比如 a0只被赋值了一次,说明没有线程安全问题了
* (在这个例子中,redisson 连接redis只是用来做分布式锁,真正的业务中的redis操作用的还是其他连接方式,比如 jedisPool 等)
*
* 1556505103008--Thread-4--key:a0不存在,设置值为: Thread-4 Thread-2--key:a0存在,值为:
* Thread-4 Thread-3--key:a0存在,值为: Thread-4
* 1556505103035--Thread-4--key:a1不存在,设置值为: Thread-4 Thread-2--key:a1存在,值为:
* Thread-4 Thread-3--key:a1存在,值为: Thread-4
* 1556505103058--Thread-4--key:a2不存在,设置值为: Thread-4 Thread-2--key:a2存在,值为:
* Thread-4 Thread-3--key:a2存在,值为: Thread-4
* 1556505103080--Thread-4--key:a3不存在,设置值为: Thread-4 Thread-2--key:a3存在,值为:
* Thread-4 Thread-3--key:a3存在,值为: Thread-4
* 1556505103100--Thread-4--key:a4不存在,设置值为: Thread-4 Thread-2--key:a4存在,值为:
* Thread-4 Thread-3--key:a4存在,值为: Thread-4
* 1556505103126--Thread-4--key:a5不存在,设置值为: Thread-4 Thread-2--key:a5存在,值为:
* Thread-4 Thread-3--key:a5存在,值为: Thread-4
* 1556505103146--Thread-2--key:a6不存在,设置值为: Thread-2 Thread-4--key:a6存在,值为:
* Thread-2 Thread-3--key:a6存在,值为: Thread-2
* 1556505103165--Thread-4--key:a7不存在,设置值为: Thread-4 Thread-2--key:a7存在,值为:
* Thread-4 Thread-3--key:a7存在,值为: Thread-4
* 1556505103186--Thread-4--key:a8不存在,设置值为: Thread-4 Thread-2--key:a8存在,值为:
* Thread-4 1556505103197--Thread-4--key:a9不存在,设置值为: Thread-4
* Thread-2--key:a9存在,值为: Thread-4 Thread-3--key:a8存在,值为: Thread-4
* Thread-3--key:a9存在,值为: Thread-4
*/ }

---------------------------------------------------

注意:

如果不是想用分布式锁解决其他业务逻辑问题,而只是为了解决本文标题说的向redis中存入取出值(如果存在就取出,如果不存在就存入)的问题,那么完全可以用下面的方法来实现

 其原理就是下面这个方法:
// jedis.set("key", "value", "nx", "ex", 50L); //第一个参数:key,第二个参数:value,第三、四个参数固定写法,第五个参数:超时毫秒值
// 上面这个方法其实就是redis的 setnx 和 expire 组合在一起的原子指令 (据说其是Redis2.8版本增加的新特性,但是我在2.4版本居然也能用)
    public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 10; j++) {
int k = j;
// 连接本地的 Redis 服务
// Jedis jedis = new Jedis("localhost");
// 创建连接池对象
JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);
// 从连接池中获取一个jedis对象
Jedis jedis = jedisPool.getResource();
String setResult = jedis.set("a" + k, Thread.currentThread().getName(), "nx", "ex", 50L);
if (setResult == null) {
// 说明已经存在,设置值失败
System.out.println(Thread.currentThread().getName() + "--key:" + ("a" + k) + "存在,值为: "
+ jedis.get("a" + k));
} else {
// 说明设置值成功
System.out.println(System.currentTimeMillis() + "--" + Thread.currentThread().getName()
+ "--key:" + ("a" + k) + "不存在,设置值为: " + Thread.currentThread().getName());
}
jedis.close();
}
}
}).start();
}
} // 运行结果: 说明这是没有问题的
// 也就是说,如果不是想用分布式锁解决其他业务逻辑问题,而只是为了解决向redis中存入取出值(如果存在就取出,如果不存在就存入)的问题,那么完全可以用上面的方法来实现
// 其原理就是下面这个方法:
// jedis.set("key", "value", "nx", "ex", 50L); //第一个参数:key,第二个参数:value,第三、四个参数固定写法,第五个参数:超时毫秒值
// 上面这个方法其实就是redis的 setnx 和 expire 组合在一起的原子指令 (据说其是Redis2.8版本增加的新特性,但是我在2.4版本居然也能用)
// 1556588977532--Thread-0--key:a0不存在,设置值为: Thread-0
// Thread-1--key:a0存在,值为: Thread-0
// Thread-2--key:a0存在,值为: Thread-0
// 1556588977535--Thread-0--key:a1不存在,设置值为: Thread-0
// Thread-2--key:a1存在,值为: Thread-0
// Thread-1--key:a1存在,值为: Thread-0
// 1556588977538--Thread-0--key:a2不存在,设置值为: Thread-0
// Thread-2--key:a2存在,值为: Thread-0
// Thread-1--key:a2存在,值为: Thread-0
// 1556588977541--Thread-0--key:a3不存在,设置值为: Thread-0
// 1556588977545--Thread-0--key:a4不存在,设置值为: Thread-0
// Thread-1--key:a3存在,值为: Thread-0
// Thread-2--key:a3存在,值为: Thread-0
// Thread-2--key:a4存在,值为: Thread-0
// 1556588977553--Thread-0--key:a5不存在,设置值为: Thread-0
// Thread-1--key:a4存在,值为: Thread-0
// 1556588977558--Thread-0--key:a6不存在,设置值为: Thread-0
// 1556588977562--Thread-0--key:a7不存在,设置值为: Thread-0
// Thread-1--key:a5存在,值为: Thread-0
// Thread-2--key:a5存在,值为: Thread-0
// 1556588977566--Thread-0--key:a8不存在,设置值为: Thread-0
// Thread-2--key:a6存在,值为: Thread-0
// Thread-1--key:a6存在,值为: Thread-0
// 1556588977578--Thread-0--key:a9不存在,设置值为: Thread-0
// Thread-2--key:a7存在,值为: Thread-0
// Thread-1--key:a7存在,值为: Thread-0
// Thread-2--key:a8存在,值为: Thread-0
// Thread-1--key:a8存在,值为: Thread-0
// Thread-2--key:a9存在,值为: Thread-0
// Thread-1--key:a9存在,值为: Thread-0

从redis中取值如果不存在设置值,使用Redisson分布式锁【我】的更多相关文章

  1. 多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中【我】

    多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中 package com.xxx.xx.reve.service; import java.util.ArrayL ...

  2. Redisson 分布式锁实现之前置篇 → Redis 的发布/订阅 与 Lua

    开心一刻 我找了个女朋友,挺丑的那一种,她也知道自己丑,平常都不好意思和我一块出门 昨晚,我带她逛超市,听到有两个人在我们背后小声嘀咕:"看咱前面,想不到这么丑都有人要." 女朋友 ...

  3. 时间轮机制在Redisson分布式锁中的实际应用以及时间轮源码分析

    本篇文章主要基于Redisson中实现的分布式锁机制继续进行展开,分析Redisson中的时间轮机制. 在前面分析的Redisson的分布式锁实现中,有一个Watch Dog机制来对锁键进行续约,代码 ...

  4. Jquery系列:checkbox 获取值、选中、设置值、事件监听等操作

    <div id="divId" class="divTable"> <div class="tableBody"> ...

  5. C# Winform中WebBrowser给网页中的input控件赋值/设置值

    订阅WebBrowser的DocumentCompleted事件,在里面写入 private void browser_DocumentCompleted(object sender, WebBrow ...

  6. 《Redis深度历险:核心原理和应用实践》千帆竞发——分布式锁

  7. spring-boot 中实现标准 redis 分布式锁

    一,前言 redis 现在已经成为系统缓存的必备组件,针对缓存读取更新操作,通常我们希望当缓存过期之后能够只有一个请求去更新缓存,其它请求依然使用旧的数据.这就需要用到锁,因为应用服务多数以集群方式部 ...

  8. Redis 中的事务分析,Redis 中的事务可以满足ACID属性吗?

    Redis 中的事务 什么是事务 1.原子性(Atomicity) 2.一致性(Consistency) 3.隔离性(Isolation) 4.持久性(Durability) 分析下 Redis 中的 ...

  9. redis中如何对 key 进行分类

    因为redis中的 hash是不支持设置过期时间的,如果我们要 设置过期时间,还要分类存储,可以用下面折中的方法 其实就是我们把 key 定义的有规律一些,通过在key的字符串内部 分类,上图只是因为 ...

随机推荐

  1. 设计模式 - 单例模式(Singleton Pattern)

    单例模式 介绍 模式:创建型 意图:保证一个类只有一个实例,并提供一个访问它的全局访问点 解决:一个全局使用的类频繁地创建与销毁 场景: 唯一序列号 web中的计数器 I/O与数据库的连接 …… 实现 ...

  2. CAD 在ARCGIS中的坐标系问题

    近期在使用服务(文本写入dxf方式)导出CAD的时候发现导出的CAD文件和原始数据在ArcMap中叠加后不能重合,出现了错位的现象. 查看CAD文件后发现CAD的坐标系及投影和数据不一致导致的.遇到这 ...

  3. OpenCL洗牌函数shuffle

    在OpenCL中,经常会碰到会对向量的多个分量进行交叉运算的情况,比如 float4 d4; //input float scale; //input float2 mix_0 = mix((floa ...

  4. JavaScript 节流函数 Throttle 详解

    在浏览器 DOM 事件里面,有一些事件会随着用户的操作不间断触发.比如:重新调整浏览器窗口大小(resize),浏览器页面滚动(scroll),鼠标移动(mousemove).也就是说用户在触发这些浏 ...

  5. Go 反射

    基本了解 在Go语言中,大多数时候值/类型/函数非常直接,要的话,定义一个.你想要个Struct type Foo struct { A int B string } 你想要一个值,你定义出来 var ...

  6. centos7的主机名配置

    centos7的主机名配置 方法一:通过配置文件/etc/hostname (重启后生效) 方法二:通过命令hostnamectl  set-hostname    新主机名(会自动把主机名改为小写) ...

  7. 一:SqlServer中的 CEILING函数和 FLOOR函数以及ROUND()

    例如 1.ROUND() 格式为ROUND(y1,y2,y3) y1:要被四舍五入的数字y2:保留的小数位数 y3:为0,可以不写,y1进行四舍五入,不为0则y1不进入四舍五入,如果y1有值就直接根据 ...

  8. C#几个经常用到的字符串的截取

    string str="123abc456";int i=3;1 取字符串的前i个字符   str=str.Substring(0,i); // or  str=str.Remov ...

  9. windows docker redis

    拉取docker docker pull hub.c.163.com/library/redis:latest 启动docker docker run -p 6379:6379 -d hub.c.16 ...

  10. 【博客导航】Nico博客导航汇总

    摘要 介绍本博客关注的内容大类.任务.工具方法及链接,提供Nico博文导航. 导航汇总 [博客导航]Nico博客导航汇总 [导航]信息检索导航 [导航]Python相关 [导航]读书导航 [导航]FP ...