循环请求接口插入数据?试试多线程操作

需求是: 同步微信公众号的文章,(微信提供文章的分页查询接口)。最开始是做的个循环请求,一千多篇文章,需要大概6分钟,太慢了。 所以我打算用多线程。

先看一下微信的接口文档。

我们看到,微信提供的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("----同步微信公众号文章完成----");

}

```

这样,第一个线程负责请求接口,第二个线程负责解析,第三个线程负责存储数据。效率大大提高了。

如有错误,请批评指正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,256评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,839评论 18 399
  • 实际上这个问题百度一大堆,但是你不一定能找到真正好的 http://blog.csdn.net/harvic880...
    感冒没吃药阅读 16,962评论 1 16
  • 今天,和几位比较有智慧的人聊了关于自己要去提升的方面。关于去接受他人的弊端,发掘弊端,去缩小别人的不足,不断去放大...
    gl秀阅读 163评论 0 0