需求是: 同步微信公众号的文章,(微信提供文章的分页查询接口)。最开始是做的个循环请求,一千多篇文章,需要大概6分钟,太慢了。 所以我打算用多线程。
先看一下微信的接口文档。
![](https://img.haomeiwen.com/i6382604/09ca5c447fefd68d.png)
我们看到,微信提供的API一次最多获取20个素材(一个素材可能包含多篇文章),经过一番测试,发现居然不是根据updateTime 倒序排序,而是通过createTime排序的,这个不知道腾讯是怎么想的。
直接上多线程实现的代码:
```
private static final LoggerLOGGER = LoggerFactory.getLogger(SyncNewsArticleJob.class);
/**
* 请求每页的条数
*/
private static final IntegerpageSize;
// 超时时间,防止某种特殊情况导致线程不中断,造成的资源浪费 1个小时
private static final Longtimeout =1L *1000 *60 *60;
@Reference(version ="1.0.0")
private WeChatNewsServiceweChatNewsService;
// 当前页
private int i ;
// 总共页 0
private int totalPage ;
//文章总数
private int newsArticleCount ;
// 开始存储标志 false
private boolean beginSaveFlag =false;
// 开始解析标志 false
private boolean beginAnalysisFlag ;
private Datedate;
//用于存放接口返回的分页字符串数据 ConcurrentHashMap
private MappageResultStrMap =new ConcurrentHashMap<>();
//用于存放解析好的实体数据 ConcurrentHashMap
private Map>newsArticleMap =new ConcurrentHashMap<>();
private void init(){
i =0;
totalPage =0;
newsArticleCount =0;
beginSaveFlag =false;
beginAnalysisFlag =false;
date =new Date();
}
```
/**
* 请求数据线程
* @author WangMin
*/
class RequestWechatimplements Runnable {
@Override
public void run() {
LOGGER.info("=========请求数据s==========");
while (i
if(timeout
LOGGER.warn("======请求超时========");
break;
}
JsonObject jsonObject = getJsonObject(i);
String resultStr =weChatNewsService.captureNews(jsonObject.toString());
// 判断Json是否正常
pageResultStrMap.put(i, resultStr);
beginAnalysisFlag =true;
i++;
}
LOGGER.info("=========请求数据e==========");
}
}
/**
* 解析数据线程
*/
class AnalysisDataimplements Runnable {
@Override
public void run() {
LOGGER.info("=========解析数据s==========");
int j =0;
while (j
if(timeout
LOGGER.warn("======解析数据超时========");
break;
}
if (beginAnalysisFlag) {
Iterator> it =pageResultStrMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
List list = jsonToBean(entry.getValue());
beginSaveFlag =true;
newsArticleMap.put(i, list);
it.remove();
j++;
}
}else {
try {
Thread.sleep(100);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
LOGGER.info("=========解析数据e==========");
}
}
/**
* 保存数据线程
* @author WangMin
* @since 2018/8/7
* @version V1.0
*/
class SaveDataimplements Runnable {
@Override
public void run() {
LOGGER.info("=========保存数据s==========");
int k =0;
while (!beginSaveFlag || (!pageResultStrMap.isEmpty() && !newsArticleMap.isEmpty()) || k
if(timeout
LOGGER.warn("======保存数据超时========");
break;
}
if (!beginSaveFlag) {
try {
Thread.sleep(100);
continue;
}catch (InterruptedException e) {
e.printStackTrace();
}
}
Iterator>> it =newsArticleMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry> entry = it.next();
newsArticleMapper.batchSaveOrUpdateNews(entry.getValue());
it.remove();
k++;
}
}
LOGGER.info("=========保存数据e==========");
}
}
public void job() {
LOGGER.debug("----同步微信公众号文章开始----");
init();
//1 获取文章分组的个数
WeChatNewsCount weChatNewsCount =weChatNewsService.countActivityQuantity();
Integer newsCount = weChatNewsCount.getNewsCount();
//2、算出分页并循环调用
totalPage = getTotalPage(newsCount);
LOGGER.info("微信公众号一共有" +totalPage +"页数据");
// 请求接口
Thread r1 =new Thread(new RequestWechat());
r1.start();
// 解析数据
Thread a1 =new Thread(new AnalysisData());
a1.start();
// 保存数据
Thread s1 =new Thread(new SaveData());
s1.start();
LOGGER.debug("----同步微信公众号文章完成----");
}
```
这样,第一个线程负责请求接口,第二个线程负责解析,第三个线程负责存储数据。效率大大提高了。
如有错误,请批评指正。
网友评论