import redis.clients.jedis.Jedis;
import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date;
/** * @author jason * @date 2019/8/17 16:09 */ public class RedisSetNXTest extends Thread{
private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX";
private String auctionCode; public RedisSetNXTest (String auctionCode) {
super(auctionCode); this.auctionCode = auctionCode; } private static int bidPrice = 100; public static void initStock(Jedis jedis,String size) {
jedis.set("StockSize",size); } public boolean subStock(Jedis jedis) {
String value=jedis.get("StockSize"); int size=Integer.parseInt(value); if((size-1)<0) {
System.out.println("用户:"+Thread.currentThread().getName() +"库存已经耗尽,抢购失败"+getSystemTime()); return false; } System.out.println("用户:"+Thread.currentThread().getName() +"当前库存="+size+"==抢购成功"+getSystemTime()); jedis.set("StockSize",--size+""); return true; } public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + "主线程运行开始!"); //更改key为a的值 Jedis jedis=new Jedis("172.31.62.131",6379); //初始化库存 initStock(jedis,"4");
//jedis.set("goodsprice","0"); //System.out.println("输出初始化值:"+jedis.get("goodsprice")+getSystemTime()); jedis.close(); RedisSetNXTest thread1 = new RedisSetNXTest("A001"); RedisSetNXTest thread2 = new RedisSetNXTest("B001"); RedisSetNXTest thread3 = new RedisSetNXTest("C001"); RedisSetNXTest thread4 = new RedisSetNXTest("D001"); RedisSetNXTest thread5 = new RedisSetNXTest("E001");
thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); try{
thread1.join(); thread2.join(); thread3.join(); thread4.join(); thread5.join(); }catch(InterruptedException e){
e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "主线程运行结束!"+getSystemTime()); }
@Override public void run() {
Jedis jedis=new Jedis("172.31.62.131",6379);
//尝试获取锁 boolean isOk= tryGetDistributedLock(jedis, "goods_lock", Thread.currentThread().getName() , 10000);
if(isOk) {
System.out.println("子线程"+this.auctionCode +"拿到锁"+getSystemTime()); subStock(jedis); System.out.println("子线程"+this.auctionCode +"释放锁"+getSystemTime()); releaseDistributedLock(jedis, "goods_lock", Thread.currentThread().getName()); }else{
while(!isOk){
//System.out.println("子线程" + auctionCode + "未拿到锁"+getSystemTime()); isOk= tryGetDistributedLock(jedis, "goods_lock", Thread.currentThread().getName() , 10000); try {
sleep(2000); } catch (InterruptedException e) {
e.printStackTrace(); } } System.out.println("子线程"+this.auctionCode +"拿到锁"+getSystemTime()); subStock(jedis); System.out.println("子线程"+this.auctionCode +"释放锁"+getSystemTime()); releaseDistributedLock(jedis, "goods_lock", Thread.currentThread().getName()); } jedis.close(); System.out.println(Thread.currentThread().getName() + "线程运行结束"+getSystemTime()); } /** * 业务逻辑处理 * */ public void doSomething(Jedis jedis) {
String v = jedis.get("goodsprice"); Integer iv = Integer.valueOf(v); //条件都给过 if(bidPrice > iv){
Integer bp = iv + 100; //出价成功,事务未提交 jedis.set("goodsprice",String.valueOf(bp)); System.out.println("子线程"+this.auctionCode +", 出价:"+ jedis.get("goodsprice") +",出价时间:" +getSystemTime()); }else{
System.out.println("子线程"+this.auctionCode +"出价低于现有价格!"+getSystemTime()); } } /** * 尝试获取分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @param expireTime 超期时间 * @return 是否获取成功 */ public boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true; } return false;
}
private static final Long RELEASE_SUCCESS = 1L;
/** * 释放分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @return 是否释放成功 */ public boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1])else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {
return true; } return false;
} public static String getSystemTime() {
Date now = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");//可以方便地修改日期格式 String times = dateFormat.format( now ); System.out.println(times); return times; } } |