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([email protected]/ReferencePipeline.java:176)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining([email protected]/ArrayList.java:1655)
at java.util.stream.AbstractPipeline.copyInto([email protected]/AbstractPipeline.java:484)
at java.util.stream.AbstractPipeline.wrapAndCopyInto([email protected]/AbstractPipeline.java:474)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential([email protected]/ReduceOps.java:913)
at java.util.stream.AbstractPipeline.evaluate([email protected]/AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect([email protected]/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 杀死重启了。


