论坛首页 入门技术论坛

项目中遇到的 Java啤酒爆炸

浏览 1454 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-06-18   最后修改:2009-06-18

    最近在做一项目,其中有一模块需要在页面上配置第三方提供的程序路径,配置完成后系统定时执行(quartz),也可以在页面上手动执行,ajax调用后台方法,执行第三方提供的程序,只要是读取固定格式的文件解析成图片,存到本地目录和数据库中。当要解析的文件很大的时候,就会遇到啤酒爆炸的问题。。。

    File file = new File(pro);
        if (file.exists()) {
          logger.info("seed程序开始执行....");
          ProcessBuilder procBuilder = new ProcessBuilder(file.getAbsolutePath());
          procBuilder.redirectErrorStream(true); //合并输出子进程的standard和error inputstream
          logger.info("合并子进程InputStream{}",procBuilder.redirectErrorStream());
          Process process = procBuilder.start();
         
          drainInBackground(process.getInputStream());
          int exit = process.waitFor();
          logger.info("seed程序退出{}", exit);
          josnResult = "exeok";
        } else {
          logger.info("seed程序未找到....");
          josnResult = "notfound";
        }

 

    /**
   * 启动一个线程,用于排空子进程的输出流,否则子进程会挂起
   */
  static void drainInBackground(final InputStream is) {
    new Thread(new Runnable() {
      public void run() {
        try {
          while (is.read() >= 0)
            ;
        } catch (IOException e) {
          // return on IOException
        }
      }
    }).start();
  }

 

    这里的教训是: 为了确保子进程能够结束,你必须排空它的输出流;对于错误流(error stream)也是一样,而且它可能会更麻烦,因为你无法预测进程什么时候会倾 倒(dump)一些输出到这个流中。在 5.0 版本中,加入了一个名为ProcessBuilder 的类用于排空这些流。它的 redirectErrorStream 方法将各个流合并起来,所以你只需要排空这一个流。如果你决定不合并输出流和错误流,你必须并行地 (concurrently)排空它们。试图顺序化地(sequentially)排空它们会导致子进程被挂起。

论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics