多线程下载,每个下载线程中使用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吗?

解决方案 »

  1.   

    可能我没有表述清楚。我所说的多线程,是指同时有多个线程正在下载不同的url,但是每一个下载任务只有一个线程。每一个下载任务分别写到不同名称的文件中。而且,绝大多数情况下,下载是正常的。只有网络环境很复杂时(很多人正在使用,而且变化频繁),才有部分线程执行.read()超过几分钟,个别线程一直在执行.read(),就没法关闭正在读写的文件对象raf。
    **************************************************
    问题的关键是出现这种情况时如何释放文件呢?这些一直没有关闭的文件后续也要进行写操作啊... ....
      

  2.   

    是不是newf,raf这两个对象应该在下载线程外定义?这样,可以根据线程的状态,在线程外部强行关闭raf?这是我想到的一个可能的解决办法。
      

  3.   

    这个情况是有一定几率发生的。。多线程多的时候有时候会卡住。。
    解决思路是每一个连接线程加一个看门狗。。如果发现超时,强行关闭
    此外,尽可能的用异步线程。这样一个线程万一关闭失败,也不影响其他的
    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 }
      

  4.   

    可以看下这篇文章是否对你有效:http://www.importnew.com/21015.html 
      

  5.   

    我怎么觉得,问题的关键在你下载的服务器端,它在繁忙的时候会与你的server之间有链接时间过长的问题,
    下手处理那些与服务器连接等待时间长的线程就可以了吧
      

  6.   

    http://blog.csdn.net/ritterliu/article/details/7453264看一下这个,让线程暂停,等其他的任务结束后再唤醒这个