[英]Java thread not progressing in a JDBC program
我试图在源和目标上查找数据库所有表中的行数,源是Greenplum,目标是Hive(在HDFS上)。 为了进行并行处理,我创建了两个线程,这些线程调用分别计算两端计数的方法。 该代码可以在下面看到:
new Thread(new Runnable() {
@Override
public void run() {
try {
gpTableCount = getGpTableCount();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
hiveTableCount = getHiveTableCount();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
while(!(gpTableCount != null && gpTableCount.size() > 0 && hiveTableCount != null && hiveTableCount.size() > 0)) {
Thread.sleep(5000);
}
两个线程的结果都存储在两个单独的Java Hashmap中。 以下是用于计算GP计数的计数。 除数据库名称外,Hive计数的计算方法相同,因此我只给出了一种方法。
public Map<String,String> getGpTableCount() throws SQLException {
Connection gpAnalyticsCon = (Connection) DbManager.getGpConnection();
while(keySetIterator_gpTableList.hasNext()) {
gpTabSchemakey = keySetIterator_gpTableList.next();
tablesnSSNs = gpTabSchemakey.split(",");
target = tablesnSSNs[1].split(":");
analyticsTable = target[0].split("\\.");
gpCountQuery = "select '" + analyticsTable[1] + "' as TableName, count(*) as Count, source_system_name, max(xx_last_update_tms) from " + tablesnSSNs[0] + " where source_system_name = '" + target[1] + "' group by source_system_name";
try {
gp_pstmnt = gpAnalyticsCon.prepareStatement(gpCountQuery);
ResultSet gpCountRs = gp_pstmnt.executeQuery();
while(gpCountRs.next()) {
gpCountRs.getLong(2) + ", Max GP Tms: " + gpCountRs.getTimestamp(4).toString());
gpDataMap.put(gpCountRs.getString(1) + "," + gpCountRs.getString(3), gpCountRs.getLong(2) + "," + gpCountRs.getTimestamp(4).toString());
}
} catch(org.postgresql.util.PSQLException e) {
e.printStackTrace();
} catch(SQLException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("GP Connection closed");
gp_pstmnt.close();
gpAnalyticsCon.close();
return gpDataMap;
}
蜂巢的方法:
public Map<String, String> getHiveTableCount() throws IOException, SQLException {
Connection hiveConnection = DbManager.getHiveConnection();
while(hiveIterator.hasNext()) {
gpHiveRec = hiveIterator.next();
hiveArray = gpHiveRec.split(",");
hiveDetails = hiveArray[1].split(":");
hiveTable = hiveDetails[0].split("\\.");
hiveQuery = "select '" + hiveTable[1] + "' as TableName, count(*) as Count, source_system_name, max(xx_last_update_tms) from " + hiveDetails[0] + " where source_system_name='" + hiveDetails[1] + "' group by source_system_name";
try {
hive_pstmnt = hiveConnection.prepareStatement(hiveQuery);
ResultSet hiveCountRs = hive_pstmnt.executeQuery();
while(hiveCountRs.next()) {
hiveDataMap.put(hiveCountRs.getString(1) + "," + hiveCountRs.getString(3), hiveCountRs.getLong(2) + "," + hiveCountRs.getTimestamp(4).toString());
}
} catch(HiveSQLException e) {
e.printStackTrace();
} catch(SQLException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
}
return hiveDataMap;
}
提交jar时,将启动两个线程,并且开始同时执行GP&Hive的SQL查询。 但是这里的问题是,一旦GP的线程完成方法的执行: getGpTableCount()
,我就会看到打印语句: GP Connection closed
,并且配置单元的线程在恢复之前至少挂了30分钟。 如果检查了Hive表上的锁,以防万一没有锁。 30-40分钟后,配置单元线程再次开始并结束。 即使配置单元上的表数量较少(例如20个表),也会发生这种情况。
这是我提交罐子的方式:
/usr/jdk64/jdk1.8.0_112/bin/java -Xdebug -Dsun.security.krb5.debug=true -Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.krb5.realm=PROD.COM -Djava.security.krb5.kdc=ip-xx-xxx-xxx-xxx.ec2.internal -Djavax.security.auth.useSubjectCredsOnly=false -jar /home/etl/ReconTest/ReconAuto_Test_Prod.jar
任何人都可以让我知道在代码中创建线程的方式是否存在问题,以及如何解决该问题?
假设您的gpTableCount
和hiveTableCount
是正常的HashMap
,那么您将遇到同步问题。
这是一个广泛的主题,需要在此处进行详细说明,但这是一个简短的介绍:
由于它们是在不同的线程中填充的,因此在内存同步之前,您的主线程不会“看到”这些更改。 无法保证何时发生这种情况(最好假定除非您强制执行,否则永远不会发生)。
要正确执行此操作,请使用线程安全版本(请参阅Collections.synchronizedMap或ConcurrentHashMap ),或在同一监视器上手动同步检查。 (即,但将自身检查在synchronized
方法中,并将填充地图的代码也置于同步方法中)。 或者,您可以将count本身放入两个volatile
int
,并在其他两个线程中进行更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.