用到的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. vue+原生JavaScript实现slideDown与slideUp[简单思路]

    整个代码如下: <template> <div style="width:400px;margin:100px auto;"> <div class= ...

  2. 解决PostGIS打开shp文件输入输出模块出现"找不到文件libintl-9.dll"的问题

    找到shp2pgsql-gui.exe这个程序的目录 复制一份libintl-8.dll副本,改名为libintl-9.dll即可.

  3. APP请求服务器数据-HttpUrlConnection

    1. 实例化URL对象 首先第一步实例化一个URL对象,传入参数为请求的数据的网址. URL url = new URL("http://www.imooc.com/api/teacher? ...

  4. socket通信如何处理每次包长度不定问题

    说起来,这是一个漫长的问题: 客户端和服务器通信的结构是:包头+数据长度+数据 客户端请求服务器发送200包数据.包头=request:长度=4(一个int),数据=200: 服务器在收到客户端的请求 ...

  5. 基于Netty 实现简单的私有协议

    原文链接 基于Netty 实现简单的私有协议 代码仓库地址 基于Netty 实现简单的私有协议 在学习了Netty的不同的编码器和解码器之后,我们可以通过编解码器实现简单的自定义协议,这个自定义的协议 ...

  6. mysql7笔记----存储过程实例

    mysql创建存储过程 DROP PROCEDURE IF EXISTS getCreateTimes /*前面要写DELIMITER $$ 或DELIMITER // */ DELIMITER $$ ...

  7. C#自定义控件添加到工具箱

    1.在需要使用这个自定义控件的项目中,在引用中,右键,添加引用,浏览,找到dll(如:ComButton.dll),进行添加,这时候,控件应该是能够自动添加到工具箱的. 2.在Visual Studi ...

  8. 数据结构学习之栈求解n皇后问题

    数据结构学习之栈求解n皇后问题 0x1 目的 ​ 深入掌握栈应用的算法和设计 0x2 内容 ​ 编写一个程序exp3-8.cpp求解n皇后问题. 0x3 问题描述 即在n×n的方格棋盘上,放置n个皇后 ...

  9. Linux新手随手笔记1.1

    ifconfig   查询网卡信息 分别是网卡名称,物理IP地址,MAC地址,RX收到数据包大小,TX发送数据包大小 # uname # uname -a 查看内核版本号 # hostname 查看主 ...

  10. 分析dhcp.lease文件,统计DHCP服务器IP自动分配

    #!/usr/bin/env python # coding=utf-8 import string import time,datetime class TIMEFORMAT: def __init ...