zoukankan      html  css  js  c++  java
  • 多线程并发安全计数器实现限流(一) 简单实现

        面试题目:如何实现限流

        思路: 限制同一时间段的请求数量,即使用计数器来限制请求的数量。

                   请求开始加1,请求结束减1;

        思路实现代码

    @RestController
    public class Demo1_CounterTest {
    
        Counter counter = new CounterBasic();
    
        int limit = 3000;
    
        @RequestMapping("/hello")
        public void hello() {
    
            counter.incr();
            // 请求超过限制
            if (counter.get() > limit) {
                // 限流
                return;
            }
    
            try {
                // 业务逻辑
            } finally {
                // 处理完毕, 数量减一
                counter.decr();
            }
        }
    }
    

      

    创建一个计数器接口

    public interface Counter {
        /**
         * increase 1
         * @return
         */
        int incr();
    
        /**
         * decrease 1
         * @return
         */
        int decr();
    
        /**
         * get current num
         * @return
         */
        int get();
    }
    

      

    实现计数器接口

    public class CounterBasic implements Counter {
    
        volatile int i = 0; // 本质是修改内存中某一个变量的值
    
        public int incr() {
            // 字节码
            // 1. 获取i的值 getfield #2 <com/tony/edu/juc/atomic/CounterBasic.i>
            int cuurent = i;
    
            // 2. 进行计算(+1) iadd
            int result = cuurent + 1;
    
            // 3. 赋值 putfield #2 <com/tony/edu/juc/atomic/CounterBasic.i>
            i = result;
    
            return result;
        }
    
        public int decr() {
            return i--;
        }
    
        @Override
        public int get() {
            return i;
        }
    }
    

      

    测试计时器

     public static void main(String[] args) throws InterruptedException {
            final Counter ct = new CounterBasic();
    
            //模拟多线程场景
            CountDownLatch countDownLatch = new CountDownLatch(2);
    
            for (int i = 0; i < 2; i++) {
                new Thread(() -> {
                    long begin = System.nanoTime();
                    for (int j = 0; j < 10000; j++) {
                        ct.incr();
                    }
                    System.out.println("done...运算时间: " + (System.nanoTime() - begin));
                    countDownLatch.countDown();
                }).start();
            }
    
            countDownLatch.await();
            System.out.println("计数器最终结果: " + ct.get());
            // 预期结果应该 --- 20000
        }
    

    如果结果时正确的话,应该打印出 20000

    打印结果,显示不是 两万

    done...运算时间: 767900
    done...运算时间: 387000
    计数器最终结果: 19885

    从结果可以发现, 该计数器并不能实现线程高并发安全

  • 相关阅读:
    杭电 2546 饭卡 (01背包问题)
    杭电2602 Bone Collector
    01背包问题的详细概述
    杭电1003 最大子串(第二次AC) 当作DP的训练吧
    杭电1087 Super Jumping! Jumping! Jumping!(初见DP)
    Virtualenv虚拟环境的创建、激活、及退出
    修改maven本地仓库路径
    PPT如何去除背景音乐(史上最全方案)
    NVIDIA显卡驱动安装步骤
    Python之NumPy(axis=0 与axis=1)区分
  • 原文地址:https://www.cnblogs.com/Jomini/p/13621757.html
Copyright © 2011-2022 走看看