分享

oschina 用于记录浏览数的源码

 CevenCheng 2012-04-18


oschina 用于记录浏览数的源码

红薯 发布于 2011年01月07日 9时, 18评/2452阅 59人收藏此代码, 我要收藏
包括软件、新闻和话题以及代码在内的信息,用户访问过一次就会给访问次数字段增1。在oschina上这个操作是异步的,访问的时候只是将数据在内存中保存,每隔固定时间将这些数据写入数据库。
有两个注意实现(详看代码中的注释): 
1. 当tomcat停止时而且尚未达到运行周期时将剩余数据写回 
2. 必须显式关闭数据库连接,因为线程的运行不受Filter控制,无法自动关闭连接,如果不关闭会导致连接泄漏 
这个类提供了一个main方法可直接运行,需要用到此类的时候,只需要将自己的写数据库逻辑填充上即可。 
具体使用方法请看 main 函数。 

代码片段(1)

[文件] VisitStatService.java ~ 3KB    下载(192)

001package net.oschina.service;
002 
003import java.util.*;
004import java.util.concurrent.*;
005 
006import org.apache.commons.logging.Log;
007import org.apache.commons.logging.LogFactory;
008 
009/**
010 * 访问统计服务
011 * @author Winter Lau
012 * @date 2011-1-6 下午03:49:40
013 */
014public class VisitStatService extends TimerTask {
015 
016    private final static Log log = LogFactory.getLog(VisitStatService.class);
017    private static boolean start = false;
018    private static VisitStatService daemon;
019    private static Timer click_timer;
020    private final static long INTERVAL = 60 1000;
021     
022    /**
023     * 支持统计的对象类型
024     */
025    private final static byte[] TYPES = new byte[]{
026        0x01,0x02,0x03,0x04,0x05
027    };
028     
029    //内存队列
030    private final static ConcurrentHashMap<Byte, ConcurrentHashMap<Long, Integer>> queues =
031        new ConcurrentHashMap<Byte, ConcurrentHashMap<Long, Integer>>(){{
032            for(byte type : TYPES)
033                put(type, new ConcurrentHashMap<Long, Integer>());
034        }};
035 
036    /**
037     * 记录访问统计
038     * @param type
039     * @param obj_id
040     */
041    public static void record(byte type, long obj_id) {
042        ConcurrentHashMap<Long, Integer> queue = queues.get(type);
043        if(queue != null){
044            Integer nCount = queue.get(obj_id);
045            nCount = (nCount==null)?1:nCount+1;
046            queue.put(obj_id, nCount.intValue());
047            System.out.printf("record (type=%d,id=%d,count=%d)\n",type,obj_id,nCount);
048        }
049    }
050 
051    /**
052     * 启动统计数据写入定时器
053     * @param ctx
054     */
055    public static void start() {
056        if(!start){
057            daemon = new VisitStatService();
058            click_timer = new Timer("VisitStatService"true);
059            click_timer.schedule(daemon, INTERVAL, INTERVAL);//运行间隔1分钟
060            start = true;
061        }
062        log.info("VisitStatService started.");
063    }
064 
065    /**
066     * 释放Service
067     */
068    public static void destroy(){
069        if(start){
070            click_timer.cancel();
071            start = false;
072        }
073        log.info("VisitStatService stopped.");
074    }
075     
076    @Override
077    public void run() {
078        for(byte type : TYPES){
079            ConcurrentHashMap<Long, Integer> queue = queues.remove(type);
080            queues.put(type, new ConcurrentHashMap<Long, Integer>());
081            try{
082                _flush(type, queue);
083            }catch(Throwable t){
084                log.fatal("Failed to flush click stat data.", t);
085                //此处发送异常报告
086            }finally{
087                //此处关闭数据库连接
088            }
089        }
090    }
091     
092    @Override
093    public boolean cancel() {
094        boolean b = super.cancel();
095        //写回剩余数据,Tomcat停止时不会丢失数据
096        this.run();
097        return b;
098    }
099     
100    /**
101     * 写访问统计数据到数据库
102     * @param type
103     * @param queue
104     */
105    private void _flush(byte type, ConcurrentHashMap<Long, Integer> queue){
106        if(queue.size()==0)
107            return ;
108        switch(type){
109            //数据写入数据库....
110        }
111        System.out.printf("Flush to database: type=%d\n", type);
112    }
113 
114    /**
115     * 测试
116     * @param args
117     * @throws Exception
118     */
119    public static void main(String[] args) throws Exception {
120        start();
121        for(int i=0;i<10;i++)
122            new Timer("OfferTask_"+(i+1), false).schedule(
123                    new TimerTask(){
124                        private Random rnd = newRandom(System.currentTimeMillis());           
125                        @Override
126                        public void run() {
127                            record(TYPES[rnd.nextInt(TYPES.length)],rnd.nextInt(10));
128                        }      
129                    },
130                01000
131            );
132    }
133     
134}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多