概述
2019独角兽企业重金招聘Python工程师标准>>>
每次收到点击请求,将文章id放进一个队列里,然后开启一个轮询服务,隔五秒去update到数据库中。每次查询到的文章点击量,有可能是未及时更新的(时效性要求不高)。
使用ConcurrentLinkedQueue 作为队列,因为它线程安全, 长度足够满足需要
public class CargroupService implements ICargroupService {
private final static Log log = LogFactory.getLog(CargroupService.class);
/** 文章访问队列 **/
public static ConcurrentLinkedQueue<String> articleClickQueue = new ConcurrentLinkedQueue<String>();
/** 定时更新点击量线程 **/
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
/** 更新线程是否启动 **/
private static volatile boolean isStartScheduled = false;
@Override
public void getArticleDetail(ArticleQuery query) {
// 利用线程安全的队列来保存被点击的文章,然后定时更新数据库
String queueStr = dbInfo.getId()+";"+ip;
articleClickQueue.offer(queueStr);
if (isStartScheduled == false) {
log.debug("初始化文章点击量线程");
synchronized (CargroupService.class) {
if (isStartScheduled == false) {
isStartScheduled = true;
ArticleClickThread thread = new ArticleClickThread(articleService, labelInfoService);
scheduledExecutorService.scheduleAtFixedRate(thread, 0, CommonPropertiesConstants.COLLECT_CLICKNUM_SENONDS, TimeUnit.SECONDS);
}
}
}
}
}
保存线程代码
public class ArticleClickThread implements Runnable {
private final static Log log = LogFactory.getLog(ArticleClickThread.class);
@Override
public void run() {
List<Map<String, Integer>> updateList = new ArrayList<Map<String, Integer>>();
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
while (!CargroupService.articleClickQueue.isEmpty()) {
String articleIdAndIp = CargroupService.articleClickQueue.poll();
String[] strs = StringUtils.split(articleIdAndIp, ";");
Integer id = Integer.parseInt(strs[0]);
String ip = strs[1];
String articleIdAndIpRedisKey = RpcToolUtils.getArticleIdAndIpRedisKey(String.valueOf(id), ip);
boolean exit = false;
try {
exit = RedisDataSource.existsObject(articleIdAndIpRedisKey);
} catch (Exception e) {
log.error("Redis服务挂了---------- !" + e);
exit = false;
e.printStackTrace();
}
if (exit == false) {
try {
// 把该ip访问的文章记录,1天内重新点击或者刷新,不计数
RedisDataSource.setObject(articleIdAndIpRedisKey, "1", 24*60*60);
} catch (Exception e) {
e.printStackTrace();
}
if (!map.containsKey(id)) {
map.put(id, 1);
} else {
map.put(id, map.get(id) + 1);
}
}
}
for (Integer idKey : map.keySet()) {
Map<String, Integer> paramMap = new HashMap<String, Integer>();
paramMap.put("articleId", idKey);
paramMap.put("clickTimes", map.get(idKey));
updateList.add(paramMap);
}
if (updateList != null && updateList.size() > 0) {
articleService.batchUpdateClickNum(updateList);
labelInfoService.batchUpdateClickNum(updateList);
}
log.debug("完成轮询任务:保存文章点击量");
}
第一次启动线程后,每次点击文章只需 往队列里扔文章id,等待被轮询线程保存到数据库。
转载于:https://my.oschina.net/u/1423640/blog/798831
最后
以上就是无私跳跳糖为你收集整理的文章点击量 高并发 java的全部内容,希望文章能够帮你解决文章点击量 高并发 java所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复