限流--基于某个滑动时间窗口限流

基于linkedqueue 的滑动时间窗口限流

package com.heshen.algorithm.leakybucket;

import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.IntStream;

public class TimeWindow {
    private ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();

    private int seconds;

    private int max;
    public TimeWindow(int max, int timeWindowOfSeconds){
        this.seconds = timeWindowOfSeconds;
        this.max = max;

        new Thread(new Runnable(){

            @Override
            public void run() {

                for(;;){
                    clean();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }

            }
        }).start();
    }

    /**
     * 获取令牌,并且添加时间
     */
    public void take(){


        long start = System.currentTimeMillis();
        try {


            int size = sizeOfValid();
            if (size > max - 1) {
                System.err.println(" full queue:size:" + queue.size() + ",max:" + max + ",queue:" + printQueue());
                throw new IllegalStateException("full");
            }
            synchronized (queue) {
                if (sizeOfValid() > max - 1) {
                    System.err.println(" full queue: in synchronized,size:" + queue.size() + ",max:" + max + ",queue:" + printQueue());
                    throw new IllegalStateException("full");

                }
                this.queue.offer(System.currentTimeMillis());
            }

            System.out.println(" queue: d,size:" + queue.size() + ",max:" + max + ",queue:" + printQueue());
        }finally {
            System.out.println("cost:"+(System.currentTimeMillis()  - start) + " ms");
        }

    }

    private String printQueue(){

        Iterator it = queue.iterator();
        StringBuilder sb = new StringBuilder();
        while (it.hasNext()){
           Long t = it.next();
           sb.append(" ").append(t);
        }
        return sb.toString();
    }



    public int sizeOfValid(){


        Iterator it = queue.iterator();

        Long ms = System.currentTimeMillis() - seconds * 1000;

        int count = 0;
        while (it.hasNext()){
           long t = it.next();
           if(t > ms){
               count++;
           }
        }

        return count;
    }

    /**
     * 清理
     */
    public void clean(){
        Long c = System.currentTimeMillis() - seconds * 1000;

        Long tl = null;

        System.out.println("peek: "+queue.peek() +"c:"+ c);

        while((tl = queue.peek()) != null && tl < c){
            System.out.println("peek: t:"+ tl);
            queue.poll();
        }
    }
    public static void main(String[] args){

        final TimeWindow timeWindow = new TimeWindow(200, 2);

        IntStream.range(0, 100).forEach((i)->{
            new Thread(() -> {

                for(;;){
                    System.out.println("before take i:"+i);

                    try {
                        Thread.sleep(new Random().nextInt(20)* 100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try{
                        timeWindow.take();

                        System.out.println("some option, i:"+i);

                    }catch (Exception e){
                        System.err.println(" take i:"+i +", encounter error:"+ e.getMessage());
                        try {
                            Thread.sleep(10L);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        continue;

                    }

                    System.out.println("after take i:"+i);
                }


            }).start();
        });

    }
}

需求在某个滑动的时间窗口内,限定访问次数

你可能感兴趣的:(java)