zoukankan      html  css  js  c++  java
  • 如何防止秒杀抢购超卖?

    可以利用redis的事务加上watch监听方法,具体代码如下!

      1 package com.github.distribute.lock.redis;
      2 
      3 import java.util.List;
      4 import java.util.Set;
      5 import java.util.concurrent.ExecutorService;
      6 import java.util.concurrent.Executors;
      7 
      8 import redis.clients.jedis.Jedis;
      9 import redis.clients.jedis.Transaction;
     10 
     11 /**
     12  * redis乐观锁实例
     13  * @author linbingwen
     14  *
     15  */
     16 public class OptimisticLockTest {
     17 
     18     public static void main(String[] args) throws InterruptedException {
     19         long starTime=System.currentTimeMillis();
     20 
     21         initPrduct();
     22         initClient();
     23         printResult();
     24 
     25         long endTime=System.currentTimeMillis();
     26         long Time=endTime-starTime;
     27         System.out.println("程序运行时间: "+Time+"ms");
     28 
     29     }
     30 
     31     /**
     32      * 输出结果
     33      */
     34     public static void printResult() {
     35         Jedis jedis = RedisUtil.getInstance().getJedis();
     36         Set<String> set = jedis.smembers("clientList");
     37 
     38         int i = 1;
     39         for (String value : set) {
     40             System.out.println("第" + i++ + "个抢到商品,"+value + " ");
     41         }
     42 
     43         RedisUtil.returnResource(jedis);
     44     }
     45 
     46     /*
     47      * 初始化顾客开始抢商品
     48      */
     49     public static void initClient() {
     50         ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
     51         int clientNum = 10000;// 模拟客户数目
     52         for (int i = 0; i < clientNum; i++) {
     53             cachedThreadPool.execute(new ClientThread(i));
     54         }
     55         cachedThreadPool.shutdown();
     56 
     57         while(true){
     58             if(cachedThreadPool.isTerminated()){
     59                 System.out.println("所有的线程都结束了!");
     60                 break;
     61             }
     62             try {
     63                 Thread.sleep(1000);
     64             } catch (InterruptedException e) {
     65                 e.printStackTrace();
     66             }
     67         }
     68     }
     69 
     70     /**
     71      * 初始化商品个数
     72      */
     73     public static void initPrduct() {
     74         int prdNum = 100;// 商品个数
     75         String key = "prdNum_100001";
     76         String clientList = "clientList";// 抢购到商品的顾客列表
     77         Jedis jedis = RedisUtil.getInstance().getJedis();
     78 
     79         if (jedis.exists(key)) {
     80             jedis.del(key);
     81         }
     82 
     83         if (jedis.exists(clientList)) {
     84             jedis.del(clientList);
     85         }
     86 
     87         jedis.set(key, String.valueOf(prdNum));// 初始化
     88         RedisUtil.returnResource(jedis);
     89     }
     90 
     91 }
     92 
     93 /**
     94  * 顾客线程
     95  *
     96  * @author linbingwen
     97  *
     98  */
     99 class ClientThread implements Runnable {
    100     Jedis jedis = null;
    101     String key = "prdNum_10001";// 商品主键
    102     String clientList = "clientList";//// 抢购到商品的顾客列表主键
    103     String clientName;
    104 
    105     public ClientThread(int num) {
    106         clientName = "编号=" + num;
    107     }
    108 
    109     public void run() {
    110         try {
    111             Thread.sleep((int)(Math.random()*5000));// 随机睡眠一下
    112         } catch (InterruptedException e1) {
    113         }
    114         while (true) {
    115             System.out.println("顾客:" + clientName + "开始抢商品");
    116             jedis = RedisUtil.getInstance().getJedis();
    117             try {
    118                 jedis.watch(key);
    119                 int prdNum = Integer.parseInt(jedis.get(key));// 当前商品个数
    120                 if (prdNum > 0) {
    121                     Transaction transaction = jedis.multi();
    122                     transaction.set(key, String.valueOf(prdNum - 1));
    123                     List<Object> result = transaction.exec();
    124                     if (result == null || result.isEmpty()) {
    125                         System.out.println("悲剧了,顾客:" + clientName + "没有抢到商品");// 可能是watch-key被外部修改,或者是数据操作被驳回
    126                     } else {
    127                         jedis.sadd(clientList, clientName);// 抢到商品记录一下
    128                         System.out.println("好高兴,顾客:" + clientName + "抢到商品");
    129                         break;
    130                     }
    131                 } else {
    132                     System.out.println("悲剧了,库存为0,顾客:" + clientName + "没有抢到商品");
    133                     break;
    134                 }
    135             } catch (Exception e) {
    136                 e.printStackTrace();
    137             } finally {
    138                 jedis.unwatch();
    139                 RedisUtil.returnResource(jedis);
    140             }
    141 
    142         }
    143     }
    144 
    145 }
  • 相关阅读:
    BNU 51002 BQG's Complexity Analysis
    BNU OJ 51003 BQG's Confusing Sequence
    BNU OJ 51000 BQG's Random String
    BNU OJ 50999 BQG's Approaching Deadline
    BNU OJ 50998 BQG's Messy Code
    BNU OJ 50997 BQG's Programming Contest
    CodeForces 609D Gadgets for dollars and pounds
    CodeForces 609C Load Balancing
    CodeForces 609B The Best Gift
    CodeForces 609A USB Flash Drives
  • 原文地址:https://www.cnblogs.com/WPF0414/p/9991704.html
Copyright © 2011-2022 走看看