当遇到代码中某句话或某个方法会卡死的情况,我们该如何处理呢?
比如这段:
// 保存原文信息
try {
List<ContentSource> tempContents = new LinkedList<ContentSource>(contents);
StoreHelper helper = new StoreHelper(PropertiesUtil.hbaseIp, PropertiesUtil.hbasePort);
for (int i = 0; i < tempContents.size(); i++) {
ContentSource srcContent = tempContents.get(i);
Content destContent = convertContent(srcContent);
logger.info("源码入库HBase:第--" + i + "--条:企业名称:" + destContent.getName());
helper.save(destContent); // 注意!这句可能会卡死
}
contents.clear();
} catch (Exception e) {
e.printStackTrace();
logger.info("企业html源码没有入库,请检查HBase是否正确!", e);
}
调save()的时候就有可能导致线程卡死,一直在等待,没有响应,也不报异常。
这种情况我们可以用Callable接口来对这句话设置超时处理,将这句话包进去。像这样:
public class DataManagerHbaseHelper implements Callable<String> {
private Content content;
private StoreHelper helper;
public Content getContent() {
return content;
}
public void setContent(Content content) {
this.content = content;
}
public StoreHelper getHelper() {
return helper;
}
public void setHelper(StoreHelper helper) {
this.helper = helper;
}
@Override
public String call() throws Exception {
helper.save(content);
return "true";
}
}
我们把 helper.save(destContent); 这句需要的两个对象封到新的DataManagerHbaseHelper里面,以保证不改变原来代码,只检测超时。然后在call()方法中调用这句话。 在原始类中使用这个类来调用这句话并设置超时参数如下:
// 保存原文信息
try {
List<ContentSource> tempContents = new LinkedList<ContentSource>(contents);
StoreHelper helper = new StoreHelper(PropertiesUtil.hbaseIp, PropertiesUtil.hbasePort);
for (int i = 0; i < tempContents.size(); i++) {
ContentSource srcContent = tempContents.get(i);
Content destContent = convertContent(srcContent);
logger.info("源码入库HBase:第--" + i + "--条:企业名称:" + destContent.getName());
// ☆重点在这里
//防止Hbase异常停止造成的存储线程停止
DataManagerHbaseHelper dmh = new DataManagerHbaseHelper();
dmh.setContent(destContent);
dmh.setHelper(helper);
ExecutorService exec = Executors.newCachedThreadPool();
Future<String> submit = exec.submit(dmh);
exec.shutdown();
String reCode = submit.get(30000, TimeUnit.MILLISECONDS); // 第一个参数设置超时时长,此处我设置为3s
if(reCode.equals("true")){
logger.info("存储hbase成功");
}
}
contents.clear();
}catch (InterruptedException e){
e.printStackTrace();
logger.info("Hbase存储程序阻塞,请检查HBase是否正常!", e);
}
catch (ExecutionException e){
e.printStackTrace();
logger.info("Hbase存储程序阻塞,请检查HBase是否正常!", e);
}
catch (TimeoutException e){
e.printStackTrace();
logger.info("Hbase存储程序阻塞,请检查HBase是否正常!", e);
}
catch (Exception e) {
e.printStackTrace();
logger.info("企业html源码没有入库,请检查HBase是否正确!", e);
}
这样就可以控制这一句话超时时长了,时长可以自己定义,如果过长就会报TimeoutException。