/**
* 首次启动加载数据至缓存
*/
public class ApplicationStartTask { private static Logger logger = LoggerFactory.getLogger(ApplicationStartTask.class);
private AtomicInteger loadNum = new AtomicInteger(0); @Autowired
private FaceProducer cacheSynchronizationProducer;
@Autowired
private FaceConsumer cacheSynchronizationConsumer; @Autowired
private FaceInfoService faceInfoService; /**
* 当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,
* <br>等到需要执行的任务数大于线程池基本大小时就不再创建
*/
private static final int POOL_CORE_SIZE = Runtime.getRuntime().availableProcessors(); /**
* 线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务
*/
private static final int POOL_MAX_SIZE = Runtime.getRuntime().availableProcessors(); /**
* 线程池的工作线程空闲后,保持存活的时间 <br>
* 单位:分
*/
private static final int POOL_KEEP_ALIVE_TIME = 2; @Autowired
@Qualifier("sqliteManagerImpl")
private SqlieteManager sqlieteManager; @Autowired
private FaceCompareManager faceCompareManager; @Value("${local.sqlite.sqlname}")
private String sqlName; @Bean
public ApplicationStartTask loadCache() {
logger.info("[启动任务]首次启动载入数据至缓存...");
checkSqLiteFile();
List<String> belongIds = sqlieteManager.getAllBelongIds();
if (ArrayUtil.isNotEmpty(belongIds)) { loadFromSqlite(belongIds); initMqServer(); return new ApplicationStartTask();
}
loadFromDB(); initMqServer();
return new ApplicationStartTask(); } /**
* 开启MQ服务
*/
private void initMqServer() { logger.info("开始开启MQ服务...");
cacheSynchronizationProducer.producerStart();
cacheSynchronizationConsumer.getMessage();
} /**
* 直接从MYSQL载入数据
*/
private void loadFromDB() {
logger.info("当前CPU内核线程数:{}", POOL_CORE_SIZE); long beginTimsamp = System.currentTimeMillis(); List<String> allBelongId = faceCompareManager.getAllBelongId();
int size = 0;
for (String belongId : allBelongId) {
FaceInfoSyncDataQuery query = new FaceInfoSyncDataQuery(belongId);
query.setPageSize(1000);
query.setDeleteStatus(0);
Result<Integer> result = faceInfoService.getTotalPage(query);
if (!result.isSuccess() || result.getModel() == 0) {
continue;
} int totalPage = result.getModel(); size += totalPage; }
logger.info("总任务数:{}", size);
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(POOL_CORE_SIZE, POOL_MAX_SIZE, POOL_KEEP_ALIVE_TIME,
TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(size));
CountDownLatch latch = new CountDownLatch(size); for (String belongId : allBelongId) { FaceInfoSyncDataQuery query = new FaceInfoSyncDataQuery();
query.setBelongId(belongId);
query.setDeleteStatus(0);
query.setPageSize(1000);
Result<FaceInfoSyncDataVO> result = faceInfoService.getFaces(query);
if (!result.isSuccess() || result.getModel() == null || result.getModel().getTotalPages() == 0) {
continue;
}
FaceInfoSyncDataVO faceInfoSyncDataVO = result.getModel(); int totalPage = faceInfoSyncDataVO.getTotalPages();
//第一页 poolExecutor.execute(new CacheLoadTask1(1, belongId, faceInfoSyncDataVO.getFaces(), latch));
if (totalPage == 1) {
continue;
}
for (int i = 2; i <= totalPage; i++) {
query = new FaceInfoSyncDataQuery();
query.setBelongId(belongId);
query.setPageSize(1000);
query.setPageNo(i);
query.setDeleteStatus(0);
result = faceInfoService.getFaces(query);
if (!result.isSuccess() || result.getModel() == null || ArrayUtil.isEmpty(result.getModel().getFaces())) {
continue;
}
faceInfoSyncDataVO = result.getModel(); poolExecutor.execute(new CacheLoadTask1(i, belongId, faceInfoSyncDataVO.getFaces(), latch)); }
}
try { latch.await();// 同步阻塞,直到所有线程工作完成
// long endTime = System.currentTimeMillis(); // 获取结束时间 poolExecutor.shutdown();// 不允许提交新任务,等待当前任务及队列中的任务全部执行完毕后退出
// // 支持等待以前提交的任务停止执行
// // 所有任务关闭请求或线程中断或超时,阻塞取消
// poolExecutor.awaitTermination(20, TimeUnit.MINUTES);
// poolExecutor.shutdownNow();//通过Thread.interrupt试图停止所有正在执行的线程,并不再处理还在队列中等待的任务...
} catch (Exception e) {
logger.error("[启动任务]线程池异常打印:{}", e);
poolExecutor.shutdownNow(); }
// logger.info("[启动任务]从DB中载入数据至缓存完毕!共载入{}条人脸数据", loadNum.get()); logger.info("[启动任务]完毕!全文索引{}条数据,共耗时:{}s", loadNum.get(), (System.currentTimeMillis() - beginTimsamp) / 1000); } class CacheLoadTask1 implements Runnable { private CountDownLatch latch;
List<FaceInfoDO> faceInfoDOs = null;
int putCacheNum = 0;
String belongId = null;
int pageNo = 0; public CacheLoadTask1(int pageNo, String belongId, List<FaceInfoDO> faceInfoDOs, CountDownLatch latch) {
this.latch = latch;
this.faceInfoDOs = faceInfoDOs;
this.belongId = belongId;
this.pageNo = pageNo;
// this.index = index;
} @Override
public void run() {
Long beginTime = System.currentTimeMillis();
try {
for (FaceInfoDO faceInfoDO : faceInfoDOs) {
boolean isPutCache = FaceInfoCacheManage.put(faceInfoDO);
if (isPutCache) {
putCacheNum++;
loadNum.incrementAndGet(); }
}
logger.info("[启动任务]线程{}处理完belongId-{}第{}页数据,共载入{}条人脸数据,耗时:{}ms", Thread.currentThread().getName(),
belongId, pageNo, putCacheNum, System.currentTimeMillis() - beginTime); } catch (Exception e) {
logger.error("[启动任务]载入sqlite任务[CacheLoadTask]出错:{}", e);
} finally {
// TODO: handle finally clause
latch.countDown();
}
} } /**
* 从sqlite数据库中加载数据
*/
private void loadFromSqlite(List<String> belongIds) { logger.info("当前CPU内核线程数:{}", POOL_CORE_SIZE);
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(POOL_CORE_SIZE, POOL_MAX_SIZE, POOL_KEEP_ALIVE_TIME,
TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(belongIds.size()));
CountDownLatch latch = new CountDownLatch(belongIds.size());
for (String belongId : belongIds) {
List<FaceInfoDO> faceInfoDOs = sqlieteManager.selectAllInfoByBelongId(sqlName, belongId); poolExecutor.execute(new CacheLoadTask(belongId, faceInfoDOs, latch)); } try { latch.await();// 同步阻塞,直到所有线程工作完成
// long endTime = System.currentTimeMillis(); // 获取结束时间
logger.info("[启动任务]从sqlite中载入数据至缓存完毕!共载入{}条人脸数据", loadNum.get()); poolExecutor.shutdown();// 不允许提交新任务,等待当前任务及队列中的任务全部执行完毕后退出
// // 支持等待以前提交的任务停止执行
// // 所有任务关闭请求或线程中断或超时,阻塞取消
// poolExecutor.awaitTermination(20, TimeUnit.MINUTES);
// poolExecutor.shutdownNow();//通过Thread.interrupt试图停止所有正在执行的线程,并不再处理还在队列中等待的任务...
} catch (Exception e) {
logger.error("[启动任务]线程池异常打印:{}", e);
poolExecutor.shutdownNow(); } } private void checkSqLiteFile() {
File sqliteFile = new File(sqlName + ".sqlite3");
if (!sqliteFile.exists()) {
logger.info("[启动任务]sqlite数据库未创建,开始创建...");
// 第一次启动创建本地表
try {
sqlieteManager.createTable(sqlName);
} catch (Exception e) {
logger.error(e.getMessage());
} }
} }


多线程并行_countDown的更多相关文章

  1. Java多线程--并行模式与算法

    Java多线程--并行模式与算法 单例模式 虽然单例模式和并行没有直接关系,但是我们经常会在多线程中使用到单例.单例的好处有: 对于频繁使用的对象可以省去new操作花费的时间: new操作的减少,随之 ...

  2. java8新特性(六):Stream多线程并行数据处理

    转:http://blog.csdn.net/sunjin9418/article/details/53143588 将一个顺序执行的流转变成一个并发的流只要调用 parallel()方法 publi ...

  3. MySQL 5.7主从复制从零开始设置及全面详解——实现多线程并行同步,解决主从复制延迟问题!

    MySQL 5.7主从复制从零开始设置及全面详解——实现多线程并行同步,解决主从复制延迟问题!2017年06月15日 19:59:44 蓝色-鸢尾 阅读数:2062版权声明:本文为博主原创文章,如需转 ...

  4. Python基础补充(二) 多核CPU上python多线程并行的一个假象【转】

    在python上开启多个线程,由于GIL的存在,每个单独线程都会在竞争到GIL后才运行,这样就干预OS内部的进程(线程)调度,结果在多核CPU上: python的多线程实际是串行执行的,并不会同一时间 ...

  5. C#中的多线程 - 并行编程 z

    原文:http://www.albahari.com/threading/part5.aspx 专题:C#中的多线程 1并行编程Permalink 在这一部分,我们讨论 Framework 4.0 加 ...

  6. Oracle多线程并行使用、关联与指定索引执行

    nologging AS SELECT /*+parallel(4) leading(s a) use_hash(A) index(s IDX_CS_SERVICE_RECORD_MD2_04) */ ...

  7. Optaplanner终于支持多线程并行运行 - Multithreaded incremental solving

    Optaplanner 7.9.0.Final之前,启动引擎开始对一个Problem进行规划的时候,只能是单线程进行的.也就是说,当引擎对每一个possible solution进行分数计算的过程中, ...

  8. 大数据应用之HBase数据插入性能优化之多线程并行插入测试案例

    一.引言: 上篇文章提起关于HBase插入性能优化设计到的五个参数,从参数配置的角度给大家提供了一个性能测试环境的实验代码.根据网友的反馈,基于单线程的模式实现的数据插入毕竟有限.通过个人实测,在我的 ...

  9. .Net多线程 并行编程(三)---并行集合

    为了让共享的数组,集合能够被多线程更新,我们现在(.net4.0之后)可以使用并发集合来实现这个功能. 而System.Collections和System.Collections.Generic命名 ...

随机推荐

  1. 你说说对Java中SPI的理解吧

    前言 最近在面试的时候被问到SPI了,没回答上来,主要也是自己的原因,把自己给带沟里去了,因为讲到了类加载器的双亲委派模型,后面就被问到了有哪些是破坏了双亲委派模型的场景,然后我就说到了SPI,JND ...

  2. Codeforces Edu Round 66 A-E

    A. From Hero to Zero 通过取余快速运行第一步即可.由于\(a \% b (a >= b) <= \frac{a}{2}\).所以总复杂度不超过\(O(log_2n)\) ...

  3. Servlet中获取请求参数问题

    1.GET方法,可以通过getParamter方法反复获取同一个变量的数据: 2.POST方法,需要注意请求类型(content-Type)是否是application/x-www-form-urle ...

  4. Day5 - 01 函数及函数的调用概念

    函数就是最基本的一种代码抽象的方式.函数只需写一次,就可以多次调用.Python本身内置了很多有用的函数,可以直接调用. 调用函数    要调用一个函数,需要知道函数的名称和参数.可以通过help(x ...

  5. latex参考文献删除[.s.l],[.s.n]

    用latex写毕业论文的插入会议参考论文的时候可能会遇到编译后的文档里面一堆[.s.l],[.s.n]的问题. 这是因为ref里面会议条目找不到地址信息,所以用[.s.l],[.s.n]替代,只需要更 ...

  6. 安卓和ios的app证书过期的相关问题汇总

    一,ios的APP的发布流程请见:ios的APP的发布流程 http://www.jianshu.com/p/b1b77d804254 这篇文章写得很好很全面 二,app证书过期了怎么办: IOS的情 ...

  7. SharePoint Online之通过JSOM发送邮件

    我们在SharePoint 开发过程中,经常会用到发邮件的功能,例如向Manager提醒有需要待办任务等等场景. 图片来自网站,如侵权,速删 一般我们会采用Workflow或者Power Automa ...

  8. html 01-认识Web和Web标准

    01-认识Web和Web标准 #Web.网页.浏览器 #Web Web(World Wide Web)即全球广域网,也称为万维网. 我们常说的Web端就是网页端. #网页 网页是构成网站的基本元素.网 ...

  9. react第十单元(children的深入用法-React.Children对象上的方法)

    第十单元(children的深入用法-React.Children对象上的方法) #课程目标 理解什么是children 掌握React.Children对象上的方法 #知识点 什么是children ...

  10. [日常摸鱼]bzoj2875[NOI2012]随机数生成器-矩阵快速幂

    好裸的矩阵快速幂-然而我一开始居然构造不出矩阵- 平常两个的情况都是拿相邻两项放在矩阵里拿去递推的-然后我就一直构造不出来-其实把矩阵下面弄成1就好了啊orz #include<cstdio&g ...