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

Java Process详解

 
阅读更多
Process简介

我们在实际Java开发工作中可能会遇到调用操作系统命令的场景,比如查看下文件夹,执行下sh/exe文件等等,那么我们就要用到Process了!

首先,打开API来认识下Process :

java.lang 
类 Process

java.lang.Object
  继承者 java.lang.Process
public abstract class Process
     

      extends 
      Object
     
ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

 

我们看到,Process是个抽象类,继承自“全民祖先”Object,有两种方式可以创建Process子类的实例,以及一系列进程交互方法:

方法摘要
abstract  void	destroy() 
          杀掉子进程。
abstract  int	exitValue() 
          返回子进程的出口值。
abstract  InputStream	getErrorStream() 
          获取子进程的错误流。
abstract  InputStream	getInputStream() 
          获取子进程的输入流。
abstract  OutputStream	getOutputStream() 
          获取子进程的输出流。
abstract  int	waitFor() 
          导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。

 

Process实战操练

学了那么多理论,还不如来个demo,我们来一个用“ping 百度网址”的例子吧,请看:

import java.io.IOException;

public class ProcessDemo {
	public static void main(String[] args) {
		try {
			Process process = Runtime.getRuntime().exec("ping www.baidu.com");
			System.out.println("任务执行完毕!");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

     

顺利运行,调用成功。但是结果是调用ping被挂到后台运行,程序直接打印了“任务执行完毕!”,而我们想要的效果是先把ping操作执行完成后,再输出“任务执行完毕!”。

好吧,Process提供了WaitFor和getInputStream两个方法,这两个方法都是阻塞java线程,等待脚本返回或结束后,再继续执行java程序,OK,那说改就改!

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

public class ProcessDemo {
	public static void main(String[] args) {
		try {
			Process process = Runtime.getRuntime().exec("ping www.baidu.com");
			BufferedReader bufferedReader = new BufferedReader(
					new InputStreamReader(process.getInputStream(),"gbk"));
			String line;
			while ((line = bufferedReader.readLine()) != null) {
				System.out.println(line);
			}
			System.out.println("任务执行完毕!");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

import java.io.IOException;

public class ProcessDemo {
	public static void main(String[] args) {
		try {
			Process process = Runtime.getRuntime().exec("ping www.baidu.com");
			process.waitFor();
			System.out.println("任务执行完毕!");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

这就是我们想要的啦~ 

 

问题进阶

       仔细的同学可能发现了,API文档里还有这么一句话:“创建进程的方法可能无法针对某些本机平台 上的特定进程很好地工作,比如,本机窗口进程,守护进程,Microsoft Windows 上的 Win16/DOS 进程,或者 shell 脚本。创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、 stdout 和 stderr)操作都将通过三个流 (getOutputStream()getInputStream() 和 getErrorStream()) 重定向到父进程。父进程使用这些流来提供到子进程 的输入和获得从子进程的输出。因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死锁。”

       这句话晦涩难懂,但可以简单地归纳一下,针对可执行程序的输入输出每个平台都会提供缓冲区,当没有及时把缓冲数据读出,且可执行程序在短时间内有大量数据输入缓冲区的话,缓冲区撑满,进程就会被阻塞。

       好吧,那意思很清楚了,就是让我们在写Process程序的时候,尽量主动把可执行程序的输入和输出读出来,不要让它们长时间留在缓冲区。

 

       上代码,我们先创建一个线程类,它主要负责不停地来读出Process所调用脚本的输出数据(主要的是读出error信息):

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

public class CleanInputCache extends Thread {
	private InputStream is;
	private String type;

	public CleanInputCache(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);
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
}

 

然后改造一下以上的“ping百度网址”的程序:

import java.io.IOException;

public class ProcessDemo {
	public static void main(String[] args) {
		try {
			Process process = Runtime.getRuntime().exec("ping www.baidu.com");
			new CleanInputCache(process.getInputStream(),"INFO").start();
			new CleanInputCache(process.getErrorStream(),"ERROR").start();
			process.waitFor();
			System.out.println("任务执行完毕!");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 大功告成,这样程序再也不用担心阻塞了,放心奔跑吧,process!!!

分享到:
评论

相关推荐

    Java Process详解及实例

    Java Process详解及实例 Java Process是Java语言中一个重要的概念,它允许Java程序与外部进程进行交互。通过Java Process,可以实现对外部命令的调用、文件操作、系统设置等功能。 在Java中,Process类是Java ...

    Java Process类的详解及实例代码

    Java中的`Process`类是用于表示操作系统级别的进程的抽象类。这个类允许Java应用程序与操作系统交互,执行系统命令,例如启动新的进程、读取进程的输出流、写入进程的输入流以及控制进程的生命周期。在Java中,我们...

    java 使用dos命令详解

    ### Java使用DOS命令详解 在Java开发过程中,有时候我们需要执行一些特定的操作系统命令来完成特定的任务,尤其是在Windows平台上。本文将详细介绍如何在Java中调用DOS命令,并通过具体的示例来阐述这一过程。 ###...

    java-lang包详解

    【java-lang包详解】 在Java编程语言中,`java.lang`包是所有Java程序的基础,因为它包含了许多核心类和接口,这些类和接口是编写任何Java应用程序所必需的。由于这个包是自动导入的,因此程序员无需在代码中显式地...

    Java Activiti⼯作流引擎简介详解

    Java Activiti 工作流引擎简介详解 Activiti 是一个开源的业务流程管理(BPM)框架,由 Alfresco 软件在 2010 年 5 月 17 日发布。它是一个灵活的、易扩展的可执行流程语言框架,覆盖了业务流程管理、工作流、服务...

    java调用python入门详解

    本项目名为“java调用python入门详解”,主要展示了如何在Java程序中调用Python脚本进行数据处理或其他功能实现。下面将详细介绍这个项目中的关键知识点。 1. **Jython**: 为了在Java环境中运行Python代码,我们...

    JAVA卡开发技术详解

    ### JAVA卡开发技术详解 #### 一、JAVA卡应用结构的优化 Java卡作为一种智能卡技术,因其灵活性和可扩展性被广泛应用。Java卡应用的开发与其他软件开发类似,但也有其独特之处。一个Java卡应用的核心是一个继承自`...

    Java_JNI_获得系统进程信息实例.doc

    `systemProcess.java`详解 - **静态初始化块**:通过`System.loadLibrary("process")`加载名为“process”的动态链接库(DLL)。这是JNI调用本地方法的必要步骤。 - **本地方法声明**: - `processHandle()`: 返回...

    Zookeeper Api(java)入门详解与应用场景

    **Zookeeper API(Java)入门详解** Zookeeper是一款分布式协调服务,由Apache基金会开发,它为分布式应用提供一致性服务,包括命名服务、配置管理、集群同步、分布式锁等。在Java开发中,我们通常会使用Zookeeper...

    java调用视频转换工具ffmpeg.zip

    Process process = Runtime.getRuntime().exec(command); ``` 这种方法简单直观,但不利于错误处理和复杂的参数配置。更高级的方法是使用Java库,如JNA(Java Native Access)或者Java FFmpegWrapper,它们提供了...

    java执行可执行文件或批处理

    #### exec()方法详解 `exec()`方法是`Runtime`类中的一个重要成员,它用于启动一个新进程并返回一个表示该进程的`Process`对象。该方法有多种重载形式,其中最常用的是以下两种: 1. **字符串参数**:`exec(String...

    Java多线程编程深入详解.docx

    Java多线程编程深入详解 多线程编程是Java编程语言中的一种重要技术,用于提高程序的执行效率和响应速度。在本文中,我们将深入探讨Java多线程编程的基础知识和高级技术。 什么是多进程和多线程? 在计算机科学中...

    详解Java中多进程编程的实现

    多进程编程的一个重要特点是进程间通信(IPC,Inter-Process Communication),Java中没有直接支持的原生机制,但可以通过文件、套接字或者管道等方式实现进程间的通信。例如,可以使用`Process`类的`getInputStream...

    Java软件开发实战 Java基础与案例开发详解 9-3 Rintime类的使用 共6页.pdf

    ### Java软件开发实战:Runtime类的使用 #### Runtime类概览 `Runtime`类是Java标准库中的一个重要组成部分,它提供了应用程序与运行环境之间交互的能力。由于Java程序本身是跨平台的,`Runtime`类的存在使得Java...

    java修改文件属性

    ### Java修改文件属性知识点详解 #### 一、概述 在Java编程中,对文件属性进行操作是一项常见的需求,尤其是在开发需要处理大量文件的应用程序时。本文档将详细介绍如何使用Java来判断文件是否隐藏或只读,以及...

    java_lang包详解.pdf

    `Thread`, `Compiler`, `Process`, `ThreadGroup`, `Double`, `Runtime`, `ThreadLocal`, `Float`, `RuntimePermission`, `Throwable`, `InheritableThreadLocal`, `SecurityManager`, 和 `Void`。这些类不仅提供了...

    Java调用批处理示例

    ### Java调用批处理知识点详解 #### 一、概述 在Java中,有时我们需要执行一些系统级别的任务,比如启动一个程序或执行一个脚本。此时,我们可以通过Java调用来实现这些功能。Java提供了多种方法来调用外部命令,...

    Java Runtime类详解_动力节点Java学院整理

    Process p = Runtime.getRuntime().exec("notepad"); // 在Windows上打开记事本 // ...其他处理 } catch (IOException e) { e.printStackTrace(); } ``` 三、其他功能 除了上述功能,Runtime类还包括其他一些...

    java李兴华学习笔记之Java常用类库

    #### 二、具体知识点详解 ##### 1. StringBuffer(重点) **简介**:StringBuffer是Java语言中用于处理可变字符串的一种数据结构。与String不同的是,StringBuffer的内容可以在创建后被修改。这对于需要频繁修改...

    在Java应用程序中使用JNI来监视CPU详解

    在Java应用程序中,有时需要获取CPU使用情况,但Java本身并没有提供直接的API来实现这一功能。在这种情况下,可以通过JNI(Java Native Interface)与本地代码(如C或C++)交互来实现。JNI允许Java代码调用本地方法...

Global site tag (gtag.js) - Google Analytics