用到的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. Status bar could not find cached time string image. Rendering in-process?

    在开发中,控制台经常输出“Status bar could not find cached time string image. Rendering in-process?” 在 Info.plist ...

  2. WSL(Windows Subsystem for Linux)--Pico Process Overview

    [转载] Windows Subsystem for Linux -- Pico Process Overview Overview This post discusses pico processe ...

  3. java中的重写与重载

    重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变.即外壳不变,核心重写! 重写的好处在于子类可以根据需要,定义特定于自己的行为. 也就是说子类 ...

  4. Ecto中的changeset,schema,struct,map

    概要 schema changeset struct map 总结 概要 Ecto 中, 对数据库的操作中经常用到 4 个类型: schema changeset struct map 在 Ecto ...

  5. CENTOS重新安装JDK

    centos 删除默认安装的JDK 重新安装JDK 1.删除JDK 通过xshell工具成功连接安装好的虚拟机之后可通过    rpm -qa | grep java  或 rpm -qa | gre ...

  6. 仿EXCEL插件,智表ZCELL产品V1.5 版本发布,IE8/9完全兼容

    详细请移步 智表(ZCELL)官网www.zcell.net 更新说明  这次更新主要应用户要求,主要解决了IE8/9等低版本浏览器兼容的问题,新增了部分功能,欢迎大家体验使用. 本次版本更新内容如下 ...

  7. 最新webstorm

    https://blog.csdn.net/hdp134793/article/details/81530472 最新webstorm,立即装,还有小盒子要弄个备份的,还有公交卡 2019-3-17( ...

  8. angularjs(显示和隐身) 依赖注入

    1.angularjs 隐身参数注入control: 1.control名称 , 2.function,在function内部直接传递参数和方法. var myapp=angular.model(&q ...

  9. .NET 增加扩展方法

    声明:通过一个js的实例来告诉你C#也可以实现这样的效果. 在JS中是这样实现的: 你是否见过JS中给系统默认Array对象增加一个自定义查重方法contains 在没有给Array原型上增加cont ...

  10. java-环境变量的配置

    java基础教程 链接:https://pan.baidu.com/s/1dGHrkghUJi2lew8dbWlIvg 提取码:87mi