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

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

  • 相关阅读:
    java~用域名回显照片
    java~-照片--用流回显源码
    java表单+多文件上传~~源代码
    java~生成二维码源代码
    html页面悬浮框--左边动画(隐藏凸出)---css设置
    html页面悬浮框--右边动画(隐藏凸出)---css设置
    java编写二维码
    java上传---表单+多文件上传
    js--a标签带参数href取值
    爬虫杂记
  • 原文地址:https://www.cnblogs.com/Jomini/p/13621757.html
Copyright © 2011-2022 走看看