llOVOL 2019-05-05 19:35 采纳率: 0%
浏览 270

一道javaSE编程题求大神指点

统计网站访问量,要求实现Count接口,hr方法多线程访问,要保证线程安全


要求:

  • 1.实现功能
  • 2.线程安全
  • 3.注意性能
interface Count {
    //每访问一次hr方法+1
    void hr();
    //访问状态
    DateState state();
}

class DateState {
    //最近10秒钟平均访问量
    public int last10Second;
    //最近60秒钟平均访问量
    public int last60Second;
    //最近10分钟平均访问量
    public int last10Minute;
    //最近60分钟平均访问量
    public int last60Minute;
    //60分钟平均访问量集合
    public List<Integer> last60SecondList;
}

不知道该如何计算最近时间段里的平均访问量,希望大神点拨,小弟在此感激不尽

  • 写回答

1条回答

  • llOVOL 2019-05-08 18:50
    关注

    解题思路


    先说下思路,这道题的难点在于如何获取指定时间段内的数据,在百度知识中经过一位大神提点,在hr方法中统计访问量的时候把当前时间即访问时间添加进集合中,这样就可能以当前时间为开始时间对集合进行反向遍历,开始时间减去访问时间不超过指定时间的,就进行计数,最后得到的即是最近某个时间段的访问量了。
    至于某个时间段的访问集合,考虑到性能问题不放在state方法中遍历统计,放在访问的时候就进行统计,因此定义了一个setCount方法,以第一个元素的访问时间作为开始时间开始计数,后续访问时间在指定时间段内统计其数量求平均值放进集合当中。在state方法中直接引用集合即可。

    最终代码如下:


    这里将60分钟平均访问量集合改成了60秒

    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.atomic.AtomicLong;
    
    public class CountImpl implements Count {
    
        private static final long TIME_SLOT_TEN = 10;
        private static final long TIME_SLOT_SIXTY = 60;
        private static final int INIT_VALUE = 0;
        private static final int INCR_VALUE = 1;
        private static final long TIME_10S = TimeUnit.SECONDS.toMillis(TIME_SLOT_TEN);
        private static final long TIME_60S = TimeUnit.SECONDS.toMillis(TIME_SLOT_SIXTY);
        private static final long TIME_10M = TimeUnit.MINUTES.toMillis(TIME_SLOT_TEN);
        private static final long TIME_60M = TimeUnit.MINUTES.toMillis(TIME_SLOT_SIXTY);
    
        private AtomicLong count = new AtomicLong();
        private AtomicLong start = new AtomicLong();
        private CopyOnWriteArrayList<Long> list = new CopyOnWriteArrayList();
        private AtomicInteger last60Second = new AtomicInteger();
        private CopyOnWriteArrayList<Integer> last60SecondList = new CopyOnWriteArrayList();
    
        @Override
        public void hr() {
            count.getAndIncrement();
            list.add(System.currentTimeMillis());
            setCount(System.currentTimeMillis());
        }
    
        @Override
        public DateState state() {
            DateState dateState = new DateState();
    
            long now = System.currentTimeMillis();
            int num = INIT_VALUE;
            int last10Second = INIT_VALUE;
            int last60Second = INIT_VALUE;
            int last10Minute = INIT_VALUE;
            int last60Minute = INIT_VALUE;
            for (int i = list.size() - 1; i >= 0; i--) {
                num++;
                long time = now - list.get(i);
               if (time <= TIME_60M) {
                    last60Minute = num;
                    if (time <= TIME_10S) {
                        last10Second = num;
                    }
                    if (time <= TIME_60S) {
                        last60Second = num;
                    }
                    if (time <= TIME_10M) {
                        last10Minute = num;
                    }
                } else {
                    break;
                }
            }
            System.out.println("10s内访问总量:" + last10Second);
            System.out.println("60s内访问总量" + last60Second);
            System.out.println("10m内访问总量" + last10Minute);
            System.out.println("60m内访问总量" + last60Minute);
            dateState.last10Second = last10Second / (int) TIME_SLOT_TEN;
            dateState.last60Second = last60Second / (int) TIME_SLOT_SIXTY;
            dateState.last10Minute = last10Minute / (int) TIME_SLOT_TEN;
            dateState.last60Minute = last60Minute / (int) TIME_SLOT_SIXTY;
            dateState.last60SecondList = last60SecondList;
    
            return dateState;
        }
    
        public void setCount(long time) {
            if (start.get() == INIT_VALUE) {
                start.set(time);
            }
            if (time - start.get() <= TIME_60S) {
                last60Second.set(last60Second.get() + INCR_VALUE);
            } else {
                last60SecondList.add(last60Second.get() / (int) TIME_SLOT_SIXTY);
                System.out.println("最近60秒平均访问量为:" + last60Second.get() + ",平均访问量为:" + last60Second.get() / (int) TIME_SLOT_SIXTY + ",已添加进last60SecondList集合。");
                last60Second.set(INIT_VALUE);
                start.set(INIT_VALUE);
            }
        }
    
    }
    

    测试代码


    class test {
        public static void main(String[] args) {
            CountImpl count = new CountImpl();
            ExecutorService pool = Executors.newFixedThreadPool(100);
            for (int i = 0; i < 1000; i++) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                pool.execute(new Runnable() {
                    @Override
                    public void run() {
                        count.hr();
                        System.out.println("线程:" + Thread.currentThread().getName() + "正在运行");
                    }
                });
    
            }
            pool.shutdown();
    
            DateState state = count.state();
            System.out.println("最近10s平均访问量" + state.last10Second);
            System.out.println("最近60s平均访问量" + state.last60Second);
            System.out.println("最近10m平均访问量" + state.last10Minute);
            System.out.println("最近60m平均访问量" + state.last60Minute);
            System.out.println("最近60s平均访问量集合" + state.last60SecondList);
        }
    }
    

    运行结果


    10s内访问总量:50
    60s内访问总量300
    10m内访问总量1000
    60m内访问总量1000
    最近10s平均访问量5
    最近60s平均访问量5
    最近10m平均访问量100
    最近60m平均访问量16
    最近60s平均访问量集合[5, 5, 5]

    评论

报告相同问题?

悬赏问题

  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 ubuntu系统下挂载磁盘上执行./提示权限不够
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型