java基于redis事务的秒杀实现详解编程语言

package com.vian.user.service; 
import org.junit.Test; 
import org.springframework.util.CollectionUtils; 
import redis.clients.jedis.Jedis; 
import redis.clients.jedis.JedisPool; 
import redis.clients.jedis.JedisPoolConfig; 
import redis.clients.jedis.Transaction; 
import java.io.IOException; 
import java.util.List; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
/** 秒杀测试 */ 
public class SecondKillTest { 
@Test 
public void getResult() { 
Jedis jedis = JedisPoolUtil.getJedis(); 
String goodsResult = jedis.get("goodsResult:user102"); 
System.out.println(goodsResult); 
} 
@Test 
public void test() throws IOException, InterruptedException { 
/** 初始化商品 */ 
initGoods(); 
/** 1000线程抢购100个商品 */ 
ExecutorService executorService = Executors.newFixedThreadPool(20); 
CountDownLatch count = new CountDownLatch(10000); 
long startTime = System.currentTimeMillis(); 
for (int i = 0; i < 10000; i++) { 
executorService.execute(new SecondKillHandlder("user" + i)); 
count.countDown(); 
} 
executorService.shutdown(); 
count.await(); 
long time = System.currentTimeMillis() - startTime; 
System.out.println("共耗时:" + time + "毫秒"); 
// JedisPoolUtil.close(); 
    System.in.read(); 
} 
/** 初始化商品数量 */ 
private void initGoods() { 
Jedis jedis = JedisPoolUtil.getJedis(); 
jedis.set("goods:iphone8", "100"); // 设置100个商品 
    JedisPoolUtil.returnRes(jedis); 
} 
/** 秒杀处理线程 */ 
private static class SecondKillHandlder implements Runnable { 
String goodsKey = "goods:iphone8"; // 监视的key 当前秒杀商品的数量 
    Jedis jedis; 
String userName; 
public SecondKillHandlder(String userName) { 
this.userName = userName; 
} 
@Override 
public void run() { 
while (true) { 
try { 
jedis = JedisPoolUtil.getJedis(); 
// watch 监视一个key,当事务执行之前这个key发生了改变,事务会被打断 
          jedis.watch(goodsKey); 
int currentGoodsCount = Integer.parseInt(jedis.get(goodsKey)); // 当前剩余商品数量 
if (currentGoodsCount <= 0) { 
System.out.println("商品已抢完," + userName + "---> 抢购失败 XXX"); 
break; 
} 
Transaction tran = jedis.multi(); // 开启事务 
tran.incrBy(goodsKey, -1); // 商品数量-1 
List<Object> exec = tran.exec(); // 执行事务 
if (CollectionUtils.isEmpty(exec)) { 
System.out.println(userName + "---> 抢购失败,继续抢购"); 
Thread.sleep(1); 
} else { 
exec.forEach( 
succ -> { 
String succStr = 
userName 
+ "===========================> 抢购到第【" 
+ ((100 - currentGoodsCount) + 1) 
+ "】份商品,该商品剩余:" 
+ succ.toString(); 
System.out.println(succStr); 
jedis.set("goodsResult:" + userName, succStr); // 业务代码,处理抢购成功 
                }); 
break; 
} 
} catch (Exception e) { 
e.printStackTrace(); 
} finally { 
if (jedis != null) { 
jedis.unwatch(); 
JedisPoolUtil.returnRes(jedis); 
} 
} 
} 
} 
} 
private static class JedisPoolUtil { 
private static JedisPool pool; 
private static void createJedisPool() { 
// 建立连接池配置参数 
JedisPoolConfig config = new JedisPoolConfig(); 
// 设置最大连接数 
config.setMaxTotal(100); 
// 设置最大阻塞时间,记住是毫秒数milliseconds 
config.setMaxWaitMillis(1000); 
// 设置空间连接 
config.setMaxIdle(10); 
// 创建连接池 
pool = new JedisPool(config, "192.168.31.201", 6379, 2000, null, 3); 
} 
/** 在多线程环境同步初始化 */ 
private static synchronized void poolInit() { 
if (pool == null) createJedisPool(); 
} 
/** 
* 获取一个jedis 对象 
* 
* @return 
*/ 
public static Jedis getJedis() { 
if (pool == null) poolInit(); 
return pool.getResource(); 
} 
/** 
* 归还一个连接 
* 
* @param jedis 
*/ 
public static void returnRes(Jedis jedis) { 
pool.returnResource(jedis); 
} 
public static void close() { 
pool.close(); 
} 
} 
}

 

java基于redis事务的秒杀实现详解编程语言

java基于redis事务的秒杀实现详解编程语言

 

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/16945.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论