web项目使用定时器定时聚类

来源:互联网 发布:皇朝家私 淘宝 编辑:程序博客网 时间:2024/06/17 16:18

最近项目需求:web项目已做好,某一个模块的功能是针对一条一条的数据记录进行聚类,然后向用户进行推荐。


现在问题是为了提高推荐精度,boss要求每天凌晨两点进行聚类,将聚类结果写入到本地文件。如何编写定时器成了重中之重。


上网查阅资料显示,定时器有很多种,总结一下,可以分为3种,


1、java.util包中自带的Timer,很简单,可以解决一些定时的任务


所以小主就把Timer引入到了项目中,小试了一把,是的,结果并不理想,只能做一些简单的工作,比如定时输出。不能如小主所愿定时调用聚类函数,无奈,挥泪斩之!


2、spring+quartz


网上大量网友推荐使用这个,quzrtz可以和spring集成完成优秀的定时任务,是的,确实很好!问题是小主就是定时调用聚类函数啊。弃之!


3、spring自带的定时器


简单易用,顺利的完成了小主的任务。主要步骤三步:


第一步:设置web.xml中listener



第二步:添加定时器类



第三步:配置spring中的配置文件:



函数类如下:

@Componentpublic class RecommendUtils {@Resourceprivate ProblemService service;@Resourceprivate RecordService recordService;//读取本地文件放入该Mapprivate static Map<Integer,Integer> clusterMap = null;//问题推荐条数private static final Integer RECOMMEND_SIZE = 10;//权重系数private static final Double C = 0.02;/** * 对数据库中问题内容进行聚类,并将聚类结果写入本地磁盘 */public void getClusterResults(){//读取所有问题记录List<Problem> list = null;list = service.selectAllProblemOfChecked(); // 获取所有已审核的问题//将问题迭代放入Map,<问题id,问题内容>Map<String,String> promap = new HashMap<String,String>();for(Problem pro : list){promap.put(String.valueOf(pro.getId()), pro.getContent());}ComputeTFIDF.map = promap;//1、计算各个问题的tf-idf;//2、聚类//3、将结果写入本地磁盘try {HashMap<String, HashMap<String, Double>> tf = ComputeTFIDF.tfAllFiles(ComputeTFIDF.map);HashMap<String, Double> idf = ComputeTFIDF.idf(tf);Map<String, HashMap<String, Double>> tfIdf = ComputeTFIDF.tf_idf(tf, idf);//计算各个问题的tf-idfKmeansCluster kc = new KmeansCluster();Map<String, Integer> cluster = kc.doProcess(tfIdf, 5);//聚类结果kc.printClusterResult(cluster);//写入本地磁盘} catch (IOException e) {e.printStackTrace();}}/** * 根据用户浏览记录形成推荐 */public List<Problem> recommendList(int uid){//1、读取聚类文件,以<K,V>格式保存。其中K保存类别号,V保存问题id的集合,格式如下:<10,1>try {clusterMap = RecommendUtils.readClusterFile();} catch (IOException e) {e.printStackTrace();}//2、根据用户id读取用户浏览记录,以<K,V>格式保存,K存放问题id,V存放时间戳,格式如下:<10,17865432>    //2-1读取浏览记录时设置滑动窗口,只读取一月之内的记录;    //2-2若该用户一月之内没有浏览记录,则推荐当前热点问题;List<Record> recordList = recordService.selectRecord(uid);if(recordList.size() == 0){return service.selectHotSpot();}Map<Integer,Long> recordMap = new HashMap<Integer,Long>();for(Record record : recordList){recordMap.put(record.getPid(), StringUtils.date2Long(record.getTime()));}//3、计算各类别权重//读取recordMap中每一条浏览记录,在clusterMap中找到对应的类别号//若该类别号在weightMap中不存在,则计算权重后,将类别号和权重添加到map;//若已存在,则计算权重后,将该类别号所在的权重相加;long current = new Date().getTime();Map<Integer,Double> weightMap = new HashMap<Integer,Double>();//<K:类别号,V:权重>double tmpWeight = 1- C;for(Integer record : recordMap.keySet()){            if(clusterMap.containsKey(record)){            Integer K = clusterMap.get(record);            double weight = Math.pow(tmpWeight, (current - recordMap.get(record)) / (24 * 60 * 60 * 1000));            if(weightMap.containsKey(K)){            weightMap.put(K, weightMap.get(K) + weight);            }else{            weightMap.put(K, weight);            }            } }//4、根据权重形成推荐Map<Integer,Integer> sizeMap = new HashMap<Integer,Integer>();//<K:类别号,V:推荐条数>double weightSum = 0.0;for(Integer cate : weightMap.keySet()){weightSum += weightMap.get(cate);}for(Integer cate : weightMap.keySet()){int size = (int)Math.round(RECOMMEND_SIZE * (weightMap.get(cate) / weightSum));//四舍五入取条数sizeMap.put(cate, size);}//根据类别号去clusterMap寻到对应的key,每个类别号会找到多个问题id,放到tmpList中,shuffle之后,根据sizeMap中的条数保存到最终结果resultList中List<Integer> resultList = new ArrayList<Integer>();List<Integer> tmpList = new ArrayList<Integer>();for(Integer cate : sizeMap.keySet()){for (Map.Entry<Integer, Integer> entry : clusterMap.entrySet()) {if (cate == entry.getValue()){tmpList.add(entry.getKey());}}Collections.shuffle(tmpList);for(int i = 0; i < sizeMap.get(cate); i++){resultList.add(tmpList.get(i));}tmpList.clear();}//取得resultList中的id,依次去数据库中取得问题,放入problemeList中,返回调用该方法的控制层List<Problem> problemList = new ArrayList<Problem>();for(Integer pid : resultList){Problem pro = service.selectProblemDetails(pid);problemList.add(pro);}return problemList;}/** * 按行读取读取本地聚类文件,返回map * @return map * @throws IOException  */public static Map<Integer,Integer> readClusterFile() throws IOException {FileReader fr = new FileReader("C:/cluster.txt");BufferedReader br = new BufferedReader(fr);Map<Integer,Integer> map = new HashMap<Integer,Integer>();String[] arrs;String line = "";while ((line = br.readLine()) != null) {arrs = line.split(" ");map.put(Integer.parseInt(arrs[0]), Integer.parseInt(arrs[1]));}br.close();fr.close();return map;}}

结果:

凌晨两点形成聚类

文件格式如下:

大功告成!

原创粉丝点击