多线程并发安全计数器实现限流(一) 简单实现
面试题目:如何实现限流
思路: 限制同一时间段的请求数量,即使用计数器来限制请求的数量。
请求开始加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
从结果可以发现, 该计数器并不能实现线程高并发安全

浙公网安备 33010602011771号