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语言中一个重要的概念,它允许Java程序与外部进程进行交互。通过Java Process,可以实现对外部命令的调用、文件操作、系统设置等功能。 在Java中,Process类是Java ...
Java中的`Process`类是用于表示操作系统级别的进程的抽象类。这个类允许Java应用程序与操作系统交互,执行系统命令,例如启动新的进程、读取进程的输出流、写入进程的输入流以及控制进程的生命周期。在Java中,我们...
### Java使用DOS命令详解 在Java开发过程中,有时候我们需要执行一些特定的操作系统命令来完成特定的任务,尤其是在Windows平台上。本文将详细介绍如何在Java中调用DOS命令,并通过具体的示例来阐述这一过程。 ###...
【java-lang包详解】 在Java编程语言中,`java.lang`包是所有Java程序的基础,因为它包含了许多核心类和接口,这些类和接口是编写任何Java应用程序所必需的。由于这个包是自动导入的,因此程序员无需在代码中显式地...
Java Activiti 工作流引擎简介详解 Activiti 是一个开源的业务流程管理(BPM)框架,由 Alfresco 软件在 2010 年 5 月 17 日发布。它是一个灵活的、易扩展的可执行流程语言框架,覆盖了业务流程管理、工作流、服务...
本项目名为“java调用python入门详解”,主要展示了如何在Java程序中调用Python脚本进行数据处理或其他功能实现。下面将详细介绍这个项目中的关键知识点。 1. **Jython**: 为了在Java环境中运行Python代码,我们...
### JAVA卡开发技术详解 #### 一、JAVA卡应用结构的优化 Java卡作为一种智能卡技术,因其灵活性和可扩展性被广泛应用。Java卡应用的开发与其他软件开发类似,但也有其独特之处。一个Java卡应用的核心是一个继承自`...
`systemProcess.java`详解 - **静态初始化块**:通过`System.loadLibrary("process")`加载名为“process”的动态链接库(DLL)。这是JNI调用本地方法的必要步骤。 - **本地方法声明**: - `processHandle()`: 返回...
**Zookeeper API(Java)入门详解** Zookeeper是一款分布式协调服务,由Apache基金会开发,它为分布式应用提供一致性服务,包括命名服务、配置管理、集群同步、分布式锁等。在Java开发中,我们通常会使用Zookeeper...
Process process = Runtime.getRuntime().exec(command); ``` 这种方法简单直观,但不利于错误处理和复杂的参数配置。更高级的方法是使用Java库,如JNA(Java Native Access)或者Java FFmpegWrapper,它们提供了...
#### exec()方法详解 `exec()`方法是`Runtime`类中的一个重要成员,它用于启动一个新进程并返回一个表示该进程的`Process`对象。该方法有多种重载形式,其中最常用的是以下两种: 1. **字符串参数**:`exec(String...
Java多线程编程深入详解 多线程编程是Java编程语言中的一种重要技术,用于提高程序的执行效率和响应速度。在本文中,我们将深入探讨Java多线程编程的基础知识和高级技术。 什么是多进程和多线程? 在计算机科学中...
多进程编程的一个重要特点是进程间通信(IPC,Inter-Process Communication),Java中没有直接支持的原生机制,但可以通过文件、套接字或者管道等方式实现进程间的通信。例如,可以使用`Process`类的`getInputStream...
### Java软件开发实战:Runtime类的使用 #### Runtime类概览 `Runtime`类是Java标准库中的一个重要组成部分,它提供了应用程序与运行环境之间交互的能力。由于Java程序本身是跨平台的,`Runtime`类的存在使得Java...
### Java修改文件属性知识点详解 #### 一、概述 在Java编程中,对文件属性进行操作是一项常见的需求,尤其是在开发需要处理大量文件的应用程序时。本文档将详细介绍如何使用Java来判断文件是否隐藏或只读,以及...
`Thread`, `Compiler`, `Process`, `ThreadGroup`, `Double`, `Runtime`, `ThreadLocal`, `Float`, `RuntimePermission`, `Throwable`, `InheritableThreadLocal`, `SecurityManager`, 和 `Void`。这些类不仅提供了...
### Java调用批处理知识点详解 #### 一、概述 在Java中,有时我们需要执行一些系统级别的任务,比如启动一个程序或执行一个脚本。此时,我们可以通过Java调用来实现这些功能。Java提供了多种方法来调用外部命令,...
Process p = Runtime.getRuntime().exec("notepad"); // 在Windows上打开记事本 // ...其他处理 } catch (IOException e) { e.printStackTrace(); } ``` 三、其他功能 除了上述功能,Runtime类还包括其他一些...
#### 二、具体知识点详解 ##### 1. StringBuffer(重点) **简介**:StringBuffer是Java语言中用于处理可变字符串的一种数据结构。与String不同的是,StringBuffer的内容可以在创建后被修改。这对于需要频繁修改...
在Java应用程序中,有时需要获取CPU使用情况,但Java本身并没有提供直接的API来实现这一功能。在这种情况下,可以通过JNI(Java Native Interface)与本地代码(如C或C++)交互来实现。JNI允许Java代码调用本地方法...