当前位置: 首页 > 后端技术 > Java

滑动窗口计数的Java实现——循环数组

时间:2023-04-01 22:01:58 Java

一、用圆形数组实现滑动窗口1.1.实现思路1.定义一个AtomicInteger数组,每个元素记录当前区间的计数2.定义一个长数组times,记录对应数组下标元素开始的时间。3.定义一个下标int索引记录当前正在使用的位置。4.定义每个元素的时间间隔大小span=200msindex变化如下:1.如果当前时间现在是-times[index]>span,说明当前请求计数应该在下一个元素中position.index++,如果index>=size(当前数组大小),则index=0;2、如果now-times[index]大于传入的计数时间比如1s,说明时间元素无效,重新设置:times[index]=now;array[index].set(0);1.2。计数逻辑1.锁控制2.根据上述索引逻辑更新索引,对应数组和times数组中的元素信息1.3.获取当前get方法如果在1s内锁定,会影响滑动窗口的性能,所以不锁定方法,获取的值是一个近似准确的值。实现逻辑:1.获取当前下标curIndex2。设置循环次数:时间=秒(滑动窗口统计时间)*1000/span3,开始循环,递减curIndex累加当前数组对应的值,判断条件1.当前索引对应的times[index]符合now-times[index]跨度){索引++;index=index=second*MILL){times[index]=now;this.array[index].set(0);}this.array[index].incrementAndGet();//测试打印忽略略printNum(this.array);}catch(异常e){}finally{lock.unlock();}}publicintget(){intcurIndex=index;现在很长时间=System.currentTimeMillis();整数计数=0;整数总和=0;while(count<5){if(now-times[curIndex]>=second*MILL){中断;}sum+=array[curIndex--].get();如果(curIndex<0){curIndex=size-1;}计数++;}返回总和;}/***测试代码*@paramarray*/privatesynchronizedvoidprintNum(AtomicInteger[]array){Randomrandom=newRandom();intr=random.nextInt(10);如果(r>=3){返回;}StringBuildernumBuilder=newStringBuilder();StringBuildertimeBuilder=newStringBuilder();for(inti=0;i{inttime=0;while(time<100000){intsumNow=sum.get();if(sumNow>10000){System.out.println("****************************************************");try{TimeUnit.MILLISECONDS.sleep(400+random.nextInt(30));}catch(InterruptedExceptione){e.printStackTrace();}}window.count();尝试{TimeUnit.MILLISECONDS.sleep(2+random.nextInt(30));}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("Thread:"+Thread.currentThread().getName()+",num:"+window.get());sum.incrementAndGet();}},"thread_"+i);t.开始();}尝试{TimeUnit.SECONDS.sleep(100000);}catch(InterruptedExceptione){e.printStackTrace();}}}