-
Redis+Lua实现简易的秒杀抢购
1 商品抢购
主要逻辑是:减库存,记录抢购成功的用户
@RestController
public class DemoController {
@Resource
private StringRedisTemplate stringRedisTemplate;
private static final String GOODS_STOCK_KEY = "goods:001"; // 秒杀商品库存
private static final String GOODS_USER_KEY = "users:001"; // 抢购成功的用户列表
/**
* 在不加锁的情况下,会发生超卖
*/
@GetMapping("/seckill")
public String seckill() {
int userId = (int) (Math.random() * 1000);
ValueOperations valueOps = stringRedisTemplate.opsForValue();
ListOperations listOps = stringRedisTemplate.opsForList();
int stock = Integer.parseInt(valueOps.get(GOODS_STOCK_KEY));
if (stock > 0) {
valueOps.decrement(GOODS_STOCK_KEY);
listOps.leftPush(GOODS_USER_KEY, String.valueOf(userId));
return "抢购成功";
} else {
return "商品已售罄";
}
}
/**
* 将多个命令打包成一个原子操作,利用redis单线程执行命令的特性,在不加锁的情况下避免了资源竞争
*/
@GetMapping("/seckill_lua")
public String seckill_lua() {
int userId = (int) (Math.random() * 1000);
String script = "if tonumber(redis.call('get', KEYS[1])) > 0 then " +
"redis.call('decr', KEYS[1]); " +
"redis.call('lpush', KEYS[2], ARGV[1]); " +
"return 1; " +
"else " +
"return 0; " +
"end; ";
DefaultRedisScript redisScript = new DefaultRedisScript();
redisScript.setResultType(Long.class);
redisScript.setScriptText(script);
List keyList = Arrays.asList(GOODS_STOCK_KEY, GOODS_USER_KEY);
Long result = stringRedisTemplate.execute(redisScript, keyList, String.valueOf(userId));
if (result == 1) {
return "抢购成功";
} else {
return "商品已售罄";
}
}
}
对比两次的结果:
2 多线程处理Excel导入
/**
* 多线程处理Excel导入
*
* PS:
* Executors返回的线程池对象的弊端如下:
* (1) FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
* (2) CachedThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
*/
@PostMapping
public void excelImport() throws InterruptedException {
// 待处理的数据(比如:从Excel中读取的数据)
List dataList = new ArrayList();
// 多线程处理
ExecutorService executorService = Executors.newFixedThreadPool(5);
CountDownLatch countDownLatch = new CountDownLatch(dataList.size());
for (Object obj : dataList) {
executorService.submit(new Runnable() {
@Override
public void run() {
try {
} catch (Exception ex) {
} finally {
countDownLatch.countDown();
}
}
});
}
countDownLatch.await(30, TimeUnit.SECONDS);
// 后续执行
// 返回结果
}
出处:https://www.cnblogs.com/cjsblog/p/16438567.html
栏目列表
最新更新
80386学习(二) 80386特权级保护
80386学习(一) 80386CPU介绍
8086汇编语言学习(十) 8086中断
8086汇编语言学习(九) 8086标志寄存器
8086汇编语言学习(九) 8086标志寄存器
8086汇编语言学习(八) 8086子程序
8086汇编语言学习(六) 8086处理结构化数据
8086汇编语言学习(五) 8086寻址方式
8086汇编语言学习(四) 8086汇编程序的编译
8086汇编语言学习(三) 8086中的段和栈
三大常用数据库事务详解之三:事务运行
三大常用关系型数据库事务详解之二:基
三大关系型数据库事务详解之一:基本概
MongoDB常用命令(2)
MongoDB基本介绍与安装(1)
SQLServer触发器调用JavaWeb接口
SQL Server索引的原理深入解析
SqlServer2016模糊匹配的三种方式及效率问题
SQL中Truncate的用法
sqlserver 多表关联时在where语句中慎用tri
在vscode中使用R时,用快捷键来快捷键入卡
VB.NET中如何快速访问注册表
ASP.NET中图象处理过程详解
Vue(1)Vue安装与使用
JavaScript 语言入门
js将一段字符串的首字母转成大写
纯原生html编写的h5视频播放器
H5仿原生app短信验证码vue2.0组件附源码地
TypeScript(4)接口
TypeScript(3)基础类型