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

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

  • 相关阅读:
    hdu 4893 Wow! Such Sequence!(线段树)
    Leetcode Best Time to Buy and Sell Stock II
    Debian GNU Linux服务列表的获取、服务的关闭/开启、服务在启动时是否自己主动执行的生效/失效
    R语言中数据结构
    C#编写Windows服务程序 (服务端),client使用 消息队列 实现淘宝 订单全链路效果
    deep learning实践经验总结
    Java编程思想第四版 *第五章 个人练习
    CEPH OBJECTSTORE API介绍
    leetcode(58)-Range Sum Query
    Android百日程序:GridView实现相冊效果
  • 原文地址:https://www.cnblogs.com/Jomini/p/13621757.html
Copyright © 2011-2022 走看看