用于记录浏览数的源码

来源:互联网 发布:灯光矩阵什么意思 编辑:程序博客网 时间:2024/06/06 18:06

转载http://www.oschina.net/code/snippet_12_2807?p=2#comments

看不懂,求解释


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

package net.oschina.service;import java.util.*;import java.util.concurrent.*;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * 访问统计服务 * @author Winter Lau * @date 2011-1-6 下午03:49:40 */public class VisitStatService extends TimerTask {private final static Log log = LogFactory.getLog(VisitStatService.class);private static boolean start = false;private static VisitStatService daemon;private static Timer click_timer;private final static long INTERVAL = 60 * 1000;/** * 支持统计的对象类型 */private final static byte[] TYPES = new byte[]{0x01,0x02,0x03,0x04,0x05};//内存队列private final static ConcurrentHashMap<Byte, ConcurrentHashMap<Long, Integer>> queues = new ConcurrentHashMap<Byte, ConcurrentHashMap<Long, Integer>>(){{for(byte type : TYPES)put(type, new ConcurrentHashMap<Long, Integer>());}};/** * 记录访问统计 * @param type * @param obj_id */public static void record(byte type, long obj_id) {ConcurrentHashMap<Long, Integer> queue = queues.get(type);if(queue != null){Integer nCount = queue.get(obj_id);nCount = (nCount==null)?1:nCount+1;queue.put(obj_id, nCount.intValue());System.out.printf("record (type=%d,id=%d,count=%d)\n",type,obj_id,nCount);}}/** * 启动统计数据写入定时器 * @param ctx */public static void start() {if(!start){daemon = new VisitStatService();click_timer = new Timer("VisitStatService", true);click_timer.schedule(daemon, INTERVAL, INTERVAL);//运行间隔1分钟start = true;}log.info("VisitStatService started.");}/** * 释放Service */public static void destroy(){if(start){click_timer.cancel();start = false;}log.info("VisitStatService stopped.");}@Overridepublic void run() {for(byte type : TYPES){ConcurrentHashMap<Long, Integer> queue = queues.remove(type);queues.put(type, new ConcurrentHashMap<Long, Integer>());try{_flush(type, queue);}catch(Throwable t){log.fatal("Failed to flush click stat data.", t);//此处发送异常报告}finally{//此处关闭数据库连接}}}@Overridepublic boolean cancel() {boolean b = super.cancel();//写回剩余数据,Tomcat停止时不会丢失数据this.run();return b;}/** * 写访问统计数据到数据库 * @param type * @param queue */private void _flush(byte type, ConcurrentHashMap<Long, Integer> queue){if(queue.size()==0)return ;switch(type){//数据写入数据库....}System.out.printf("Flush to database: type=%d\n", type);}/** * 测试 * @param args * @throws Exception */public static void main(String[] args) throws Exception {start();for(int i=0;i<10;i++)new Timer("OfferTask_"+(i+1), false).schedule(new TimerTask(){private Random rnd = new Random(System.currentTimeMillis());@Overridepublic void run() {record(TYPES[rnd.nextInt(TYPES.length)],rnd.nextInt(10));}}, 0, 1000);}}


0 0
原创粉丝点击