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<string, string=""> valueOps = stringRedisTemplate.opsForValue();
- ListOperations<string, string=""> 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<long> redisScript = new DefaultRedisScript();
- redisScript.setResultType(Long.class);
- redisScript.setScriptText(script);
- List<string> keyList = Arrays.asList(GOODS_STOCK_KEY, GOODS_USER_KEY);
- Long result = stringRedisTemplate.execute(redisScript, keyList, String.valueOf(userId));
- if (result == 1) {
- return "抢购成功";
- } else {
- return "商品已售罄";
- }
- }
- }</string></long></string,></string,>
复制代码 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);
- // 后续执行
- // 返回结果
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |