Java 8 的 stream 常规操作导致线程卡死

2022-08-01 17:06:01 +08:00
 coderstory

java 8 的 stream 操作导致 线程卡死

先贴一段堆栈打印 0x46 这个线程一直无法完成任务


root@data-f7b697db9-hq9lf:/app# jstack 8 | grep -A20 0x46
"http-nio-8200-exec-1" #60 daemon prio=5 os_prio=0 cpu=573228.20ms elapsed=783.76s tid=0x00007f8751e8d800 nid=0x46 runnable  [0x00007f871eaf1000]
   java.lang.Thread.State: RUNNABLE
        at java.util.stream.ReferencePipeline$2$1.accept(java.base@11.0.12/ReferencePipeline.java:176)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(java.base@11.0.12/ArrayList.java:1655)
        at java.util.stream.AbstractPipeline.copyInto(java.base@11.0.12/AbstractPipeline.java:484)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(java.base@11.0.12/AbstractPipeline.java:474)
        at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(java.base@11.0.12/ReduceOps.java:913)
        at java.util.stream.AbstractPipeline.evaluate(java.base@11.0.12/AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.collect(java.base@11.0.12/ReferencePipeline.java:578)
        at cn.bobmao.pro.data.repository.externalDataSourceHelper.DataBaseRepositoryImplCommon.getForeignKeyTable(DataBaseRepositoryImplCommon.java:32)
        at cn.bobmao.pro.data.repository.externalDataSourceHelper.DataBaseRepositoryImplCommon.getForeignKeyTable(DataBaseRepositoryImplCommon.java:40)
        at cn.bobmao.pro.data.repository.externalDataSourceHelper.DataBaseRepositoryImplCommon.getForeignKeyTable(DataBaseRepositoryImplCommon.java:40)
        at cn.bobmao.pro.data.repository.externalDataSourceHelper.DataBaseRepositoryImpl.getTableNames(DataBaseRepositoryImpl.java:66)
        at cn.bobmao.pro.data.repository.externalDataSourceHelper.ExternalDataSourceExecutor.getTableNames(ExternalDataSourceExecutor.java:57)
        at cn.bobmao.pro.data.service.ExternalDataSourceService.updateTable(ExternalDataSourceService.java:215)
        at cn.bobmao.pro.data.controller.ExternalDataSourceController.getTableInfo(ExternalDataSourceController.java:50)
        at cn.bobmao.pro.data.controller.ExternalDataSourceController$$FastClassBySpringCGLIB$$f577fbc0.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)

pid 为 70 的线程( 16 进制就是 0x46 )为异常线程

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                                                                              
     12 root      20   0 7793308   1.9g  24564 S  61.3   6.0   2:03.58 G1 Conc#0                                                                                                                                                            
     70 root      20   0 7793308   1.9g  24564 S  16.3   6.0  10:17.51 http-nio-8200-e                                                                                                                                                      
     29 root      20   0 7793308   1.9g  24564 S   5.0   6.0   0:06.73 GC Thread#1                                                                                                                                                          
     10 root      20   0 7793308   1.9g  24564 S   4.7   6.0   0:06.69 GC Thread#0                                                                                                                                                          
     15 root      20   0 7793308   1.9g  24564 S   0.7   6.0   0:01.93 VM Thread  

对应 java 代码

    @Override
   public List<String> getForeignKeyTable(List<String> tableNames, DataSourceEntity info, List<ForeignKeyInfo> foreignKeyInfos) {
       List<ColumnInfo> result = new ArrayList<>();
       List<String> allTableNames = new ArrayList<>(tableNames);
       for (String tableName : tableNames) {
           result.addAll(findAllTable(info.getDataBaseName(), tableName));
       }
       result = result.stream().filter(column -> Arrays.stream(DB_KEYWORD).noneMatch(it -> column.getColumnName().equalsIgnoreCase(it))).collect(Collectors.toList());
       Map<String, List<ColumnInfo>> tables = result.stream().collect(Collectors.groupingBy(ColumnInfo::getTableName));
       List<String> childTables = new ArrayList<>();
       for (String name : tables.keySet()) {
           List<ColumnInfo> columnInfos = tables.get(name);
           for (ColumnInfo columnInfo : columnInfos) {
               List<ForeignKeyInfo> collect = foreignKeyInfos.stream().filter(it -> it.getSourceTableName().equals(name) && it.getSourceColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList()); // 32 行
               if (!CollectionUtils.isEmpty(collect)) {
                   //获取子表的表名
                   childTables.addAll(collect.stream().map(ForeignKeyInfo::getTargetTableName).collect(Collectors.toList()));
               }
           }
       }
       if (!CollectionUtils.isEmpty(childTables)) {
           allTableNames.addAll(getForeignKeyTable(childTables, info, foreignKeyInfos)); // 40 行
       }
       return allTableNames;
   }

一脸疑问,不清楚怎么排查。。。等一会儿容器就被 k8s 杀死重启了。

5564 次点击
所在节点    Java
41 条回复
ozipin
2022-08-15 15:05:31 +08:00
是不是多表之间的外键形成了环状结构然后有没有加以检测

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/870012

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX