java 8 的 stream 操作导致 线程卡死
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
@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 杀死重启了。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.