多线程快速处理 List 集合,你学会了吗?


prtyaa
prtyaa 2023-12-30 22:10:57 65881
分类专栏: 资讯

有一个大List集合,遍历进行一些耗时操作,不能达到性能要求,查询日志,单个任务虽然有不少数据库和第三方API请求,比较耗时,但返回效率尚可,所以优先采用多线程方式进行处理并行请求数据库和第三方API,因为处理完还要对list所属的数据进行操作,所以,线程池多线程处理要等待全部处理完。

相关的代码如下:

@Test
public void testTB()
{
  List < String > list = new ArrayList < > ();
  for(int i = 0; i < 900; i++)
  {
    list.add("a");
  }
  ExecutorService touchWorker = Executors.newFixedThreadPool(4, new ThreadFactoryBuilder().setNameFormat("touch-send-worker-%d").build());
  int size = list.size();
  if(size > 100)
  {
    int batch = size % 100 == 0 ? size / 100 : size / 100 + 1;
    for(int j = 0; j < batch; j++)
    {
      int end = (j + 1) * 100;
      if(end > size)
      {
        end = size;
      }
      List < String > subList = list.subList(j * 100, end);
      touchWorker.execute(() - > sleepTest(subList));
    }
    touchWorker.shutdown();
    while(true)
    {
      if(touchWorker.isTerminated())
      {
        break;
      }
    }
  }
  else
  {
    sleepTest(list);
  }
}
private void sleepTest(List < String > subList)
{
  for(String i: subList)
  {
    try
    {
      //耗时操作
      System.out.println("######" + i + "######" + Thread.currentThread().getName());
      //                Thread.sleep(1000*30);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }
}

void shutdown()

启动一次顺序关闭,执行以前提交的任务,但不接受新任务。若已经关闭,则调用没有其他作用。

抛出:SecurityException - 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持RuntimePermission("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。

boolean isTerminated()

若关闭后所有任务都已完成,则返回true。注意除非首先调用shutdownshutdownNow,否则isTerminated永不为true。返回:若关闭后所有任务都已完成,则返回true。

当然还有一种方法,是之前写的,方法比上边的臃肿了,不过会获取返回结果进行处理:逻辑是获取所有页面的List,多线程遍历List后,将所有页面的违规词查出发送邮件,代码:

/**
 *  落地页违规词排查(多线程)。
 * @return
 */
@Test
public  void getViolationsLandpageByThreadPool() {
    try {
        landPageService.getViolationsLandpageByThreadPool("1年");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// 开始时间
long start = System.currentTimeMillis();
/*List<LandPage> list = new ArrayList<LandPage>();
for (int i = 1; i <= 3000; i++) {
    list.add(i + "");
}*/

List<LandPage> list = landPageDao.getPageIdAndPath();
// 初始化敏感词库对象
SensitiveWordInit sensitiveWordInit = new SensitiveWordInit();
// 从数据库中获取敏感词对象集合(目前先放在资源文件中,等以后比较多或者需要界面操作时再用数据库)
// 构建敏感词库
Map sensitiveWordMap = sensitiveWordInit.initKeyWord(vioKey);
// 传入SensitivewordEngine类中的敏感词库
SensitivewordEngine.sensitiveWordMap = sensitiveWordMap;
// 每500条数据开启一条线程
int threadSize = 11000;
// 总数据条数
int dataSize = list.size();
// 线程数
int threadNum = dataSize / threadSize + 1;
// 定义标记,过滤threadNum为整数
boolean special = dataSize % threadSize == 0;

/*list.parallelStream().forEach(url ->{});*/
// 创建一个线程池
ExecutorService exec = Executors.newFixedThreadPool(threadNum);
// 定义一个任务集合
List<Callable<List<LandPage>>> tasks = new ArrayList<Callable<List<LandPage>>>();
Callable<List<LandPage>> task = null;
List<LandPage> cutList = null;

// 确定每条线程的数据
for (int i = 0; i < threadNum; i++) {
    if (i == threadNum - 1) {
        if (special) {
            break;
        }
        cutList = list.subList(threadSize * i, dataSize);
    } else {
        cutList = list.subList(threadSize * i, threadSize * (i + 1));
    }
    // System.out.println("第" + (i + 1) + "组:" + cutList.toString());
    final List<LandPage> listStr = cutList;
    task = new Callable<List<LandPage>>() {

        @Override
        public List<LandPage> call() throws Exception {
//                    System.out.println(Thread.currentThread().getName() + "线程:" + listStr.get(0).getPageId());
             List<LandPage> result = new ArrayList<LandPage>();
             for (LandPage landPage : listStr) {
                 Long pageId = landPage.getPageId();
                 String path = landPage.getPath();
                 Integer version = landPage.getVersion();
                 String pageUrl = landPage.getPageUrl();
                 String actualUser = landPage.getActualUser();
                 Integer pageType = landPage.getPageType();
                 if (StringUtils.isNotBlank(path)) {
                     // 调用第一个方法,获取html字符串
                     String html = httpRequest(path);
                     // 调用第二个方法,获取包含的违规词
                     if(StringUtils.isNotBlank(html)){
                         html = html.replaceAll("<!--(.*?)-->","");
//      String buffer = htmlFiter2(html);
                        Set<String> bufferSet = SensitivewordEngine.getSensitiveWord(html, 1);// 得到敏感词有哪些,传入2表示获取所有敏感词//sensitiveWordFiltering(html);
                        /*String[] word = {"备案","错过将延误","仅需1980元"};
                        for(int i=0 ;i<word.length;i++){
                            if(html.contains(word[i])){
                                bufferSet.add(word[i]);
                            }
                        }*/
                        String[] word = {
                            "一年","1年学完","一年学完","1年内学完","一年内学完"
                        };
                        for(int i=0 ;i<word.length;i++){
                            if(html.contains(word[i])){
                                bufferSet.add(word[i]);
                            }
                        }
                        if (null!=bufferSet&&bufferSet.size()>0) {

                            String sensitiveWord = bufferSet == null ? null : bufferSet.toString();
                            if ("[]".equals(sensitiveWord)){
                                sensitiveWord = "";
                            }
                            LandPage page = new LandPage();
                            page.setPageId(pageId);
                            page.setPath(path);
                            page.setVersion(version);
                            page.setDescription(sensitiveWord);
                            page.setPageUrl(pageUrl);
                            page.setActualUser(actualUser);
                            page.setPageType(pageType);
                            result.add(page);
                            System.out.println(pageUrl);
                        }
                    }
                }
            }
            return (List<LandPage>) result;
        }
    };
    // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
    tasks.add(task);
}

List<Future<List<LandPage>>> results = exec.invokeAll(tasks);
List<LandPage> result = new ArrayList<LandPage>();
for (Future<List<LandPage>> future : results) {
    result.addAll(future.get());
}

// 关闭线程池
exec.shutdown();
System.out.println("线程任务执行结束");
System.err.println("执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");

System.out.println("共有###########"+list.size() );

result就是需要发送邮件的相关结果了

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=32789
赞同 0
评论 0 条
prtyaaL0
粉丝 1 发表 2554 + 关注 私信
上周热门
银河麒麟添加网络打印机时,出现“client-error-not-possible”错误提示  1448
银河麒麟打印带有图像的文档时出错  1365
银河麒麟添加打印机时,出现“server-error-internal-error”  1151
统信桌面专业版【如何查询系统安装时间】  1073
统信操作系统各版本介绍  1070
统信桌面专业版【全盘安装UOS系统】介绍  1028
麒麟系统也能完整体验微信啦!  984
统信【启动盘制作工具】使用介绍  627
统信桌面专业版【一个U盘做多个系统启动盘】的方法  575
信刻全自动档案蓝光光盘检测一体机  484
本周热议
我的信创开放社区兼职赚钱历程 40
今天你签到了吗? 27
信创开放社区邀请他人注册的具体步骤如下 15
如何玩转信创开放社区—从小白进阶到专家 15
方德桌面操作系统 14
我有15积分有什么用? 13
用抖音玩法闯信创开放社区——用平台宣传企业产品服务 13
如何让你先人一步获得悬赏问题信息?(创作者必看) 12
2024中国信创产业发展大会暨中国信息科技创新与应用博览会 9
中央国家机关政府采购中心:应当将CPU、操作系统符合安全可靠测评要求纳入采购需求 8

添加我为好友,拉您入交流群!

请使用微信扫一扫!