多线程任务下FileUtils.copyURLToFile引起的线程阻塞问题及Java虚拟机stac

在多线程环境下,使用FileUtils.copyURLToFile方法从URL下载图片时,发现大量线程陷入等待状态。通过Java VisualVM和jstack分析,线程因AbstractQueuedSynchronizer$ConditionObject资源等待而阻塞。问题根源在于FileUtils.copyURLToFile未设置超时,导致可能的永久阻塞。进一步排查发现HBase的ScannerTimeoutException,由于扫描超时引发异常,最终影响线程执行。解决方案包括设置FileUtils.copyURLToFile的超时时间和调整HBase的Scanner超时配置。
摘要由CSDN通过智能技术生成
导读:Java多线程开发给程序带来好处的同时,由于多线程程序导致的问题也越来越多,而且对问题的查找和分析解决对于菜鸟程序原来是是件头疼的事。下面我就项目中使用多线程开发程序过程中遇到的问题做详细的分析和解决思路的分享。

[size=medium][color=black][b]项目描述:[/b][/color][/size]
工作中要编写一份程序用于爬取某某网站上的大量图片。从HBase里面遍历出所有的爬取任务,开启固定大小的线程池Executors.newFixedThreadPool(100),提交线程,线程每个线程做的事情是使用FileUtils.copyURLToFile去从Url下载图片,保存到本地。详细代码如下:

[size=medium][color=black][b]主线程:[/b][/color][/size]

public static void getAllRecord (String tableName,String prefix,String dir) {
  
HTable table = null;
try{
table = new HTable(conf, tableName);
Scan s = new Scan();

s.setFilter(new PrefixFilter(prefix.getBytes()));
ResultScanner ss = table.getScanner(s);
ExecutorService executor = Executors.newFixedThreadPool(100);
for(Result r:ss){
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread task = new Thread(new DownLoadPicTask(r,dir,tableName));
executor.submit(task);

}
executor.shutdown();
} catch (IOException e){

}finally{
...关闭资源
}
}

[size=medium][color=black][b]任务线程:[/b][/color][/size]
public static String downloadFromUrl(String url,String dir,String cityName,String id) {  

try {
URL httpurl = new URL(url);
String fileName = getFileNameFromUrl(url);
System.out.println(fileName);
File f = new File(dir + File.separator+ cityName+ File.separator+id+File.separator+ fileName);
FileUtils.copyURLToFile(httpurl, f);

FileInputStream fis = new FileInputStream(f);
BufferedImage bufferedImg = ImageIO.read(fis);
int imgWidth = bufferedImg.getWidth();
int imgHeight = bufferedImg.getHeight();
bufferedImg = null;
fis.close();
if(imgWidth<500&&imgHeight<500){
FileUtils.deleteQuietly(f);
return null;
}
return imgWidth + "," + imgHeight;
} catch (Exception e) {
return null;
}

}

[size=medium][color=black][b]问题:[/b][/color][/size]

执行了很久很久,理论上如果任务都执行完成的话线程池会销毁,主线程会结束,可是结果是没有。第一想法是肯定哪里死锁了。于是打开Java VisualVM查看。

[img]http://www.geedoo.info/wp-content/uploads/2014/10/%E5%A4%9A%E7%B
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值