`
walsh
  • 浏览: 434837 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

Thinking In Java P550(中文版)程序代码有误

    博客分类:
  • java
阅读更多
  这一段时间在研究《Java编程思想》,个人认为第550页,18.9 进程控制,OSExecute类有问题(英文版是P944)。如果用书上的代码,程序一直就会处在阻塞的状态,更不用说,打印进程的输出信息了。
  以下是书上的代码:
 
package cn.com.newocm;

/**
 * 异常处理类 处理进程在执行过程中产生的错误
 * 
 * @author zhq
 * 
 */
public class OSExecuteException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	public OSExecuteException(String why) {
		super(why);
	}
}
 

package cn.com.newocm;

import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
 * 进程控制
 * @author zhq
 *
 */
public class OSExecute {
	public static void command(String command) {
		boolean err = false;
		try {
			Process process = new ProcessBuilder(command.split(" ")).start();
			BufferedReader results = new BufferedReader(new InputStreamReader(
					process.getInputStream()));
			String s;
			while ((s = results.readLine()) != null)//如果命令输入正确,此处一直阻塞 
				System.out.println(s);
			BufferedReader errors = new BufferedReader(new InputStreamReader(
					process.getErrorStream()));
			while ((s = errors.readLine()) != null) {
				System.err.println(s);
				err = true;
			}
		} catch (Exception e) {
			if (!command.startsWith("CMD /C"))
				command("CMD /C " + command);
			else
				throw new RuntimeException(e);
		}
		if (err)
			throw new OSExecuteException("Errors executing " + command);
	}
	
	public static void main(String[] args) {
		command("wmic process");
	}
}


上面代码执行后,没有任何反应,因为创建的进程被阻塞。原因在于,引用Java API中的原话:“有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死锁”。

  
  为了不至于出现上述问题,个人认为,需要对代码进行改进,采用多线程机制,一个线程负责读取正确信息,一个线程负责读取错误信息;在进程信息读取完毕后,应该显式的关闭进程的OutputStream。
 
   更改后的代码:
package cn.com.newcom.runtime.exec;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * 在Java内部执行Windows操作系统的程序
 * 
 * @author zhq
 * 
 */
public class OSExecute {
	public static void command(String command) {
		try {
			// 利用指定的操作系统程序和参数构造一个进程生成器
			Process process = new ProcessBuilder(command.split(" ")).start();
			// 错误的信息
			StreamGobbler errorGobbler = new StreamGobbler(process
					.getErrorStream(), "ERROR");
			// 正确的信息
			StreamGobbler outputGobbler = new StreamGobbler(process
					.getInputStream(), "OUTPUT");
			// 启动线程
			errorGobbler.start();
			outputGobbler.start();
			// 关闭进程输出流
			process.getOutputStream().close();
			// 等待该进程执行完毕
			int exitVal = process.waitFor();
			System.out.println("ExitValue: " + exitVal);
		} catch (Exception e) {
			if (!command.startsWith("cmd /C")) {
				// 只考虑了Windows 2000以上的操作系统,对于Windows 95应该是command.com  /C
				command("cmd /C " + command);
			} else
				throw new RuntimeException(e);
		}
	}

	public static void main(String[] args) {
		command("cmd /C wmic process");
	}
}

/**
 * 该线程负责读取进程输出的信息
 * 
 * @author zhq
 * 
 */
class StreamGobbler extends Thread {
	private InputStream is;
	// 输出信息的类型,错误信息,还是正确信息
	private String type;

	StreamGobbler(InputStream is, String type) {
		this.is = is;
		this.type = type;
	}

	public void run() {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String line = null;
			while ((line = br.readLine()) != null)
				System.out.println(type + ">" + line);
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
}
  


  以上只是个人的见解,有不对的地方,还请大家指教!




  
  
1
2
分享到:
评论
2 楼 暗蓝幽谷 2013-03-14  
依旧使用BufferedReader实现,不能解决“子进程阻塞,甚至死锁”的问题
1 楼 Arron.li 2010-06-03  
不错,领教了

相关推荐

    怎样使用串口登录P550

    安装操作上,需要先将线1的USB端连接到PC机,这一步骤完成后,通常需要安装对应的驱动程序。大部分情况下,购买的串口转USB线会附带驱动光盘,用户可直接安装。如果找不到驱动光盘,可以使用第三方软件,如驱动精灵...

    法高Fagoo P550/P560证卡打印机P5X0制卡机驱动程序

    法高Fagoo P550/P560证卡打印机P5X0制卡机驱动程序。Fagoo P560证卡打印机采用彩色热升华单色热转印技术,搭载OEE数码影像处理平台,为用户提供最优质的打印品质。特有的打印模式选择,满足你多方位需求。多处人性化...

    FagooC101证卡制作系统P280e、P550、P560打印排版系统

    系统内有详细的教程和帮助文档,指导用户如何进行模板设计、数据导入和打印设置。对于经验丰富的设计师,系统则提供了高级功能,如宏命令和脚本编程,满足更复杂的设计需求。 综上所述,FagooC101证卡制作系统是...

    IBM P550添加内存步骤详解

    在IBM Power System(如P550)中添加内存是一项重要的维护任务,它能提升服务器的性能,特别是在处理大量数据和并发任务时。以下是对IBM P550添加内存的详细步骤和注意事项的全面解析: 1. **升级内存前的准备**: ...

    IBM_P550_vio_规划与实施

    ### IBM P550 VIO 规划与实施:PowerVM环境下的专业知识点解析 #### 硬件环境概述 IBM P550是基于IBM Power架构的高性能服务器,适用于处理高负载应用和大规模数据处理任务。在本案例中,硬件配置如下: - 型号:...

    IBM+P550(AIX操作系统+HACMP+DS4300)安装

    中文 3. 日本語 4. 한국어 在上述内容中,我们探讨了在IBM P550服务器上安装AIX操作系统、DS4300存储设备以及HACMP高可用集群多路径软件的详细步骤。这是一个关键的IT基础设施搭建过程,对于确保业务连续性和数据...

    大话JAVA性能优化

    大话JAVA性能优化_周明耀著_北京:电子工业出版社 , 2016.04_P550

    P550小型机CPU扩容

    P550小型机CPU扩容 在P550小型机CPU扩容过程中,需要了解以下几个关键步骤: 1. 获取机器序列号:首先需要获取机器序列号,并到IBM官方网站上查找对应机型序列号的最新许可。 2. 下载最新的激活码:下载最新的...

    更换P550内存

    注意,P6-550有8个内存条插槽,按照特定的配对规则分布。 5. **更换内存**:确定故障内存条的位置,小心取出并替换为新的内存条。在操作过程中,要保护好内存插槽和新内存条不受物理损坏。 6. **恢复连接**:将...

    TMS320F28P550SJ9学习笔记12:简单的Modbus协议

    TMS320F28P550SJ9是德州仪器公司推出的一款高性能数字信号处理器(DSP),其具有强大的处理能力及丰富的外设接口,适用于工业控制等实时处理领域。Modbus协议是一种广泛使用的串行通信协议,它定义了控制器能够认识...

    TMS320F28P550SJ9学习笔记9:CPUTimer定时器配置使用-1

    文章中提到的“测试代码讲解”可能包含了一个或多个示例程序,通过这些程序可以展示定时器如何被配置和使用,以及它们是如何响应中断和完成预定任务的。这样的示例代码对于学习者来说是非常宝贵的资源,因为它不仅...

    IBM-P550-通过串口安装-AIX-6.1.doc

    根据提供的文档信息,本文将详细解析IBM P550通过串口安装AIX 6.1的操作背景、注意事项以及具体步骤。AIX是IBM的一种UNIX操作系统,广泛应用于各种IBM服务器中,包括P系列服务器。本篇文章旨在为技术人员提供一个...

    IBM_P550小型机配置ASMI管理

    ### IBM P550 小型机 ASMI 配置详解 #### 一、ASMI 简介 **高级系统管理界面**(Advanced System Management Interface, 简称 ASMI)是 IBM P5/i5 服务器提供的一个强大的管理工具。通过服务处理器(Service ...

    TMS320F28P550SJ9学习笔记2:Sysconfig 配置与点亮LED

    TMS320F28P550SJ9学习笔记2:Sysconfig 配置与点亮LED 今日学习使用Sysconfig 对引脚进行配置,并点亮开发板上的LED4 与LED5 我的单片机开发板平台是 LAUNCHXL_F28P55x 这个复制的工程文件放在C2000Ware 驱动的同一...

    IBM_P550_ds4700系统安装过程

    IBM P550和DS4700是IBM企业级服务器和存储系统的代表,它们在大型企业和数据中心中广泛使用。IBM P550是一款基于Power架构的服务器,通常运行AIX操作系统,而DS4700则是一款高端的存储阵列,提供高可用性和数据保护...

    P550 更换硬盘

    在IBM Power System P550服务器中,rootvg是系统的主要卷组,包含了操作系统和其他关键文件。当rootvg中的硬盘发生故障时,需要遵循特定的步骤来安全地更换硬盘并恢复系统的正常运行。以下是详细的操作流程: 1. **...

    TMS320F28P550SJ9学习笔记5:结构体寄存器方式配置 LED

    TMS320F28P550SJ9是德州仪器(Texas Instruments)推出的一款高性能数字信号处理器(DSP),适用于需要实时处理能力的应用场景。在这个系列的第五篇学习笔记中,重点讲解了如何使用结构体寄存器方式配置单片机的外设...

    TMS320F28P550SJ9学习笔记11:SCI通信中断-SCI-FIFO

    TMS320F28P550SJ9是德州仪器(Texas Instruments)推出的一款高性能数字信号处理器(DSP),属于C2000系列,广泛应用于实时控制领域。SCI(串行通信接口)是这类DSP中常用的一种通信方式,它支持全双工异步通信,...

    TMS320F28P550SJ9学习笔记9:CPUTimer定时器配置使用

    TMS320F28P550SJ9是德州仪器(Texas Instruments)公司生产的一款高性能数字信号处理器(DSP),属于TMS320F28P系列。该系列处理器具备先进的控制功能,特别适用于需要高速数字信号处理和精确定时的应用场景,如工业...

    TMS320F28P550SJ9学习笔记10:软件模拟I2C通信-驱动1.3寸OLED

    通过这两条线,一个I2C主设备可以和多个从设备进行通信,每个从设备都有唯一的地址标识。 首先,要通过软件模拟I2C通信,我们需要编写初始化代码,配置DSP的GPIO口作为模拟的SDA和SCL。然后,通过软件控制这些GPIO...

Global site tag (gtag.js) - Google Analytics