`
hellsing42
  • 浏览: 259366 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

StreamGobbler的详细解释

阅读更多
这是摘自《More Java pitfalls 中文版》上的例子。

先请编译和运行下面程序:
import java.util.*; 
import java.io.*; 

public class BadExecJavac2 
{ 
    public static void main(String args[]) 
    { 
        try 
        {             
            Runtime rt = Runtime.getRuntime(); 
            Process proc = rt.exec("javac"); 
            int exitVal = proc.waitFor(); 
            System.out.println("Process exitValue: " + exitVal); 
        } catch (Throwable t){ 
            t.printStackTrace(); 
        } 
    } 
}   



我们知道javac命令,当不带参数运行javac 程序时,它将输出帮助说明,为什么上面程序不产生任何输出并挂起,永不完成呢?java文档上说,由于有些本地平台为标准输入和输出流所提供的缓冲区大小有限,如果不能及时写入子进程的输入流或者读取子进程的输出流,可能导致子进程阻塞,甚至陷入死锁。所以,上面的程序应改写为:
import java.util.*; 
import java.io.*; 

public class MediocreExecJavac 
{ 
    public static void main(String args[]) 
    { 
        try 
        {             
            Runtime rt = Runtime.getRuntime(); 
            Process proc = rt.exec("javac"); 
            InputStream stderr = proc.getErrorStream(); 
            InputStreamReader isr = new InputStreamReader(stderr); 
            BufferedReader br = new BufferedReader(isr); 
            String line = null; 
            System.out.println("<ERROR>"); 
            while ( (line = br.readLine()) != null) 
                System.out.println(line); 
            System.out.println("</ERROR>"); 
            int exitVal = proc.waitFor(); 
            System.out.println("Process exitValue: " + exitVal); 
        } catch (Throwable t){ 
            t.printStackTrace(); 
        } 
    } 
} 




下面是正确的输出:

D:\java>java   MediocreExecJavac
<ERROR>
Usage: javac <options> <source files>
where possible options include:
  -g                         Generate all debugging info
  -g:none                    Generate no debugging info
  -g:{lines,vars,source}     Generate only some debugging info
  -nowarn                    Generate no warnings
  -verbose                   Output messages about what the compiler is doing
  -deprecation               Output source locations where deprecated APIs are used
  -classpath <path>          Specify where to find user class files
  -cp <path>                 Specify where to find user class files
  -sourcepath <path>         Specify where to find input source files
  -bootclasspath <path>      Override location of bootstrap class files
  -extdirs <dirs>            Override location of installed extensions
  -endorseddirs <dirs>       Override location of endorsed standards path
  -d <directory>             Specify where to place generated class files
  -encoding <encoding>       Specify character encoding used by source files
  -source <release>          Provide source compatibility with specified release

  -target <release>          Generate class files for specific VM version
  -version                   Version information
  -help                      Print a synopsis of standard options
  -X                         Print a synopsis of nonstandard options
  -J<flag>                   Pass <flag> directly to the runtime system

</ERROR>
Process exitValue: 2

D:\java>


下面是一个更一般的程序,它用两个线程同步清空标准错误流和标准输出流,并能根据你所使用的windows操作系统选择windows命令解释器command.com或cmd.exe,然后执行你提供的命令。


import java.util.*; 
import java.io.*; 

class StreamGobbler extends Thread 
{ 
    InputStream is; 
    String type;  //输出流的类型ERROR或OUTPUT 
     
    StreamGobbler(InputStream is, String type) 
    { 
        this.is = is; 
        this.type = type; 
    } 
     
    public void run() 
    { 
        try 
        { 
            InputStreamReader isr = new InputStreamReader(is); 
            BufferedReader br = new BufferedReader(isr); 
            String line=null; 
            while ( (line = br.readLine()) != null) 
            { 
                System.out.println(type + ">" + line); 
                System.out.flush(); 
            } 
            } catch (IOException ioe) 
              { 
                ioe.printStackTrace();   
              } 
    } 
} 

public class GoodWindowsExec 
{ 
    public static void main(String args[]) 
    { 
        if (args.length < 1) 
        { 
            System.out.println("USAGE: java GoodWindowsExec <cmd>"); 
            System.exit(1); 
        } 
         
        try 
        {             
            String osName = System.getProperty("os.name" ); 
            System.out.println("osName: " + osName); 
            String[] cmd = new String[3]; 

            if(osName.equals("Windows XP") ||osName.equals("Windows 2000")) 
            { 
                cmd[0] = "cmd.exe" ; 
                cmd[1] = "/C" ; 
                cmd[2] = args[0]; 
            } 
            else if( osName.equals( "Windows 98" ) ) 
            { 
                cmd[0] = "command.com" ; 
                cmd[1] = "/C" ; 
                cmd[2] = args[0]; 
            } 
             
            Runtime rt = Runtime.getRuntime(); 
            System.out.println("Execing " + cmd[0] + " " + cmd[1]+ " " + cmd[2]); 
            Process proc = rt.exec(cmd); 
            // any error message? 
            StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");        
            // any output? 
            StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT"); 
                 
            // kick them off 
            errorGobbler.start(); 
            outputGobbler.start(); 
                                     
            // any error??? 
            int exitVal = proc.waitFor(); 
            System.out.println("ExitValue: " + exitVal); 
         
        } catch (Throwable t){ 
            t.printStackTrace(); 
        } 
    } 
} 





下面是一个测试结果:

D:\java>java  GoodWindowsExec "copy Test.java Test1.java"
osName: Windows XP
Execing cmd.exe /C copy Test.java Test1.java
OUTPUT>已复制         1 个文件。
ExitValue: 0

D:\java>

下面的测试都能通过(windows xp+jdk1.5)

D:\java>java   GoodWindowsExec dir

D:\java>java   GoodWindowsExec Test.java

D:\java>java   GoodWindowsExec regedit.exe

D:\java>java   GoodWindowsExec NOTEPAD.EXE

D:\java>java   GoodWindowsExec first.ppt

D:\java>java   GoodWindowsExec second.doc


以上的意思是说如果不使用StreamGobbler把inputstream清空的话,就会造成进程被堵死,从而导致waitFor()一直等下去,永远结束不了.所以StreamGobbler作为单独的线程会自动清理inputstream防止他被堵住
分享到:
评论

相关推荐

    StreamGobbler.java

    StreamGobbler.java

    org.apache.commons.net.ftp*实现FTP下载

    利用org.apache.commons.net.ftp.*实现FTP批量下载,包括子目录文件

    ssh协议依赖jar包:ganymed-ssh2-build

    ganymed-ssh2-build ssh2 ch.ethz.ssh2.Connection ch.ethz.ssh2.SCPClient

    ganymed-ssh2-build210.jar java远程访问linux服务器操作、上传下载文件

    import ch.ethz.ssh2.StreamGobbler; import common.Logger; import org.apache.commons.lang.StringUtils; import java.io.*; import java.util.logging.Level; /** * SCP远程访问Linux服务器读取文件 * User: ...

    .2.【方法1】隐藏的弦图 (1)【课程出自拼多多店铺:北大网课资料店】

    .2.【方法1】隐藏的弦图 (1)【课程出自拼多多店铺:北大网课资料店】

    基于Selenium的Java爬虫实战(内含谷歌浏览器Chrom和Chromedriver版本115.0.5781.0)

    资源包括: 1.Java爬虫实战代码 2.selenium学习笔记 3.代码演示视频 4.谷歌浏览器chrom115.0.5781.0 chrome-linux64.zip chrome-mac-arm64.zip chrome-mac-x64.zip chrome-win32.zip chrome-win64.zip 5.谷歌浏览器驱动器Chromedriver115.0.5781.0 chromedriver-linux64.zip chromedriver-mac-arm64.zip chromedriver-mac-x64.zip chromedriver-win32.zip chromedriver-win64.zip 特别说明:Chrome 为测试版(不会自动更新) 仅适用于自动测试。若要进行常规浏览,请使用可自动更新的标准版 Chrome。)

    毕业设计参考-本科毕设时做的遥感影像分类

    毕业设计参考-本科毕设时做的遥感影像分类 本科毕业设计中的遥感影像分类是一个涉及遥感技术、图像处理和机器学习等多个领域的项目。遥感影像分类是通过计算机技术对遥感图像中的不同地物进行识别和分类的过程。以下是一个基于遥感影像分类的本科毕业设计建议: ### 1. 需求分析 - **用户角色**:确定系统的主要用户角色,如遥感影像分析人员、决策支持者等。 - **核心功能**: - 遥感影像预处理:包括影像的校正、裁剪、增强等。 - 特征提取:从遥感影像中提取有助于分类的特征。 - 分类算法实现:实现一种或多种分类算法,如监督学习、无监督学习、深度学习等。 - 结果评估:评估分类结果的准确性和可靠性。 ### 2. 技术选型 - **遥感影像处理**:使用ENVI、ERDAS Imagine等遥感影像处理软件。 - **编程语言**:Python(TensorFlow、Keras、PyTorch等)。 - **数据库**:MySQL、Oracle或PostgreSQL等。 - **服务器**:Tomcat或Jetty。 - **开发工具**:Eclipse、IntelliJ

    2024年箱包皮具行业分析报告.pptx

    行业报告

    VUE + nodejs实战

    VUE + nodejs实战

    某三层流水别墅建筑施工图水电图2g-qd-pm.dwg

    某三层流水别墅建筑施工图水电图2g-qd-pm.dwg

    2024嵌入式面试资料通用程序员简历模板700M

    2024嵌入式面试资料通用程序员简历模板700M提取方式是百度网盘分享地址

    基于Selenium的Java爬虫实战(内含谷歌浏览器Chrom和Chromedriver版本115.0.5790.170)

    资源包括: 1.Java爬虫实战代码 2.selenium学习笔记 3.代码演示视频 4.谷歌浏览器chrom115.0.5790.170 chrome-linux64.zip chrome-mac-arm64.zip chrome-mac-x64.zip chrome-win32.zip chrome-win64.zip 5.谷歌浏览器驱动器Chromedriver115.0.5790.170 chromedriver-linux64.zip chromedriver-mac-arm64.zip chromedriver-mac-x64.zip chromedriver-win32.zip chromedriver-win64.zip 特别说明:Chrome 为测试版(不会自动更新) 仅适用于自动测试。若要进行常规浏览,请使用可自动更新的标准版 Chrome。)

    2024最新Simple Allow Copy中文版

    2024最新Simple Allow Copy中文版

    基于Selenium的Java爬虫实战(内含谷歌浏览器Chrom和Chromedriver版本115.0.5767.0)

    资源包括: 1.Java爬虫实战代码 2.selenium学习笔记 3.代码演示视频 4.谷歌浏览器chrom115.0.5767.0 chrome-linux64.zip chrome-mac-arm64.zip chrome-mac-x64.zip chrome-win32.zip chrome-win64.zip 5.谷歌浏览器驱动器Chromedriver115.0.5767.0 chromedriver-linux64.zip chromedriver-mac-arm64.zip chromedriver-mac-x64.zip chromedriver-win32.zip chromedriver-win64.zip 特别说明:Chrome 为测试版(不会自动更新) 仅适用于自动测试。若要进行常规浏览,请使用可自动更新的标准版 Chrome。)

    Linux 平台下基于 Rust + GTK 开发的音乐播放器

    Linux 平台下基于 Rust + GTK 开发的音乐播放器

    毕业设计-毕设:一个血压实时监控app

    毕设:一个血压实时监控app,该app主要功能为与测量设备进行通信,获取测量数据并在客户端进行处理,由服务器进行数据 分析,为用户提供健康评估及建议。 目标 实现与蓝牙设备通信,获取使用者的心率数据和血压数据 实现数据可视化 实现将数据上传到服务器,并进行进一步分析 实现其它辅助性功能:个人信息,设置等 在完成上述功能之后,可以进一步实现其它功能,例如测量光照,温度,振动等数据 已完成功能 蓝牙功能 可以打开蓝牙并连接到指定设备获取数据流。 数据图表 已完成图表UI设计以及模块功能搭建,已实现图表数据的数据库读取功能。 个人设置 已搭建好UI,完成个人信息页面全部功能。已完成全部网络通信接口。 搭建好数据库模块以及网络通信模块 数据库功能已经实现并抽象,网络通信功能也已实现并抽象,服务器初步搭建了框架。 服务器和客户端已完成了关于User数据 和测量数据的上传下载以及清空等一系列操作,本机已通过花生壳映射到外网作为测试服务器。 服务器已有比较简单的UI可供查 询指定用户的测量数据。 状态计算 根据监控数据(振动,屏幕控制)计算用户状态,客户端算法已初步完成。 一些附加功能 已完成监听加

    基于SSM+Mysql的在线投票系统(源码+需求分析+演示视频).zip

    java语言,ssm框架,mysql数据库 前台+后台 前台界面 WU 后台界面:CQA+CQB 内容页 P2 前台 投票须知(固定IP不可重复投票) 用户注册 用户可以发起投票(包括题目,选项,单选/多选等都可以自定义) 投票主题查看,可以收藏 在线投票(按照主题投票)登录后可以操作,支持单选及多选,投票结果查看,统计(图表形式) 查看投票结果,登录后可以操作 在线留言(包括留言和管理员回复) 后台 管理员 管理员管理 注册用户审核 投票须知管理 投票主题管理 投票内容管理(选项的删除和添加) 系统管理(可以实现项目的删除和编辑以及系统配置的更新) 注册用户 个人资料修改 我的收藏主题

    鸿蒙座舱:人车交互新生态

    鸿蒙座舱:人车交互新生态 ——华为产业链深度系列研究

    2024嵌入式面试资料嵌入式八股文和相关知识

    2024嵌入式面试资料嵌入式八股文和相关知识提取方式是百度网盘分享地址

    基于Selenium的Java爬虫实战(内含谷歌浏览器Chrom和Chromedriver版本115.0.5785.0)

    资源包括: 1.Java爬虫实战代码 2.selenium学习笔记 3.代码演示视频 4.谷歌浏览器chrom115.0.5785.0 chrome-linux64.zip chrome-mac-arm64.zip chrome-mac-x64.zip chrome-win32.zip chrome-win64.zip 5.谷歌浏览器驱动器Chromedriver115.0.5785.0 chromedriver-linux64.zip chromedriver-mac-arm64.zip chromedriver-mac-x64.zip chromedriver-win32.zip chromedriver-win64.zip 特别说明:Chrome 为测试版(不会自动更新) 仅适用于自动测试。若要进行常规浏览,请使用可自动更新的标准版 Chrome。)

Global site tag (gtag.js) - Google Analytics