多线程下载,每个下载线程中使用BufferedInputStream.read(buf,0,length)来读取数据,发现在网络很繁忙时,个别线程会一直停在此语句的运行上(可以看到此时也有部分线程此语句的运行时间会比较长,比如几分钟),导致后续的写文件操作无法继续进行,因此文件始终被占用,无法进行操作。部分代码如下:
URL url = new URL(FileUrl);//FileUrl为文件下载地址
HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();
httpUrl.connect(); //连接指定的资源
InputStream is=httpUrl.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is); //获取网络输入流
newf=new File(FileDir,FileName);
raf=new RandomAccessFile(newf,"rw");//建立文件
while((size=bis.read(buf,0,buf.length))!=-1){
raf.write(buf,0,size); //数据从缓冲区写入到文件
}
raf.close();//关闭文件输出流
bis.close();//关闭缓存传输流
is.close();
****************************************************
似乎是read()阻塞导致的,有什么办法能够释放文件FileName吗?
URL url = new URL(FileUrl);//FileUrl为文件下载地址
HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();
httpUrl.connect(); //连接指定的资源
InputStream is=httpUrl.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is); //获取网络输入流
newf=new File(FileDir,FileName);
raf=new RandomAccessFile(newf,"rw");//建立文件
while((size=bis.read(buf,0,buf.length))!=-1){
raf.write(buf,0,size); //数据从缓冲区写入到文件
}
raf.close();//关闭文件输出流
bis.close();//关闭缓存传输流
is.close();
****************************************************
似乎是read()阻塞导致的,有什么办法能够释放文件FileName吗?
**************************************************
问题的关键是出现这种情况时如何释放文件呢?这些一直没有关闭的文件后续也要进行写操作啊... ....
解决思路是每一个连接线程加一个看门狗。。如果发现超时,强行关闭
此外,尽可能的用异步线程。这样一个线程万一关闭失败,也不影响其他的
public String WebpageContent(final String url, final String encode,
int timeoutSec) throws TimeoutException {
// final BufferedReader reader;
ExecutorService es = Executors.newSingleThreadExecutor();
Future<String> fut = es.submit(new Callable<String>() { @Override
public String call() throws Exception {
// core.sleep(5000);
// System.out.println("--start down page");
GetDataByURL gbc = new GetDataByURL();
gbc.refer=refer;
getDataByURL_thrdloc=(gbc);
// getDataByURL_thrdloc.get();
//reader_ThreadLocal.set(getDataByURL.reader_ThreadLocal.get());
// reader=;
// System.out.println("--start down pageww");
return gbc.downloadPage(url, encode);
}
});
try {
return (fut.get(timeoutSec, TimeUnit.SECONDS));
} catch (InterruptedException e) { e.printStackTrace();
throw new RuntimeException(e);
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
} catch (TimeoutException e) {
// System.out.println("TimeoutException");
// fut.stop
// fut.
// fut.
fut.cancel(true);
core.execMeth_Ays(new Runnable() {
@Override
public void run() {
if(getDataByURL_thrdloc!=null)
getDataByURL_thrdloc.closeStream();
}
}, "websitex close conn thread"+filex.getUUidName());
try {
fut.cancel(true);
// fut.
es.shutdown();
es.shutdownNow();
} catch (Exception e2) {
e2.printStackTrace();
}
// while (!es.isTerminated()) {
// System.out.println("start termina es pool ");
try {
// 等待关闭线程池,每次等待的超时时间为30秒 es.awaitTermination(20, TimeUnit.SECONDS);
// es.awaitTermination(3, TimeUnit.SECONDS); } catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// }
//System.out.println(es.isShutdown());// true
// System.out.println(es.isTerminated());
e.printStackTrace();
System.out.println("==webconn thread finish ");
throw e;
} finally {
try {
// fut.cancel(true);
es.shutdownNow();
} catch (Exception e2) {
e2.printStackTrace();
}
} // return }
下手处理那些与服务器连接等待时间长的线程就可以了吧