java如何添加进程_如何创建一个进程,如何进程调用进程

java一般用线程就够了,多进程优势在于每个进程互不干扰,劣势在于太耗费内存,任何事情都不是绝对的,在编写Java程序时,有时候需要在Java程序中执行另外一个程序。

1、启动程序

Java提供了两种方法用来启动其它程序:

(1)使用Runtime的exec()方法

(2)使用ProcessBuilder的start()方法

不管在哪种操作系统下,程序具有基本类似的一些属性。一个程序启动后就程序操作系统的一个进程,进程在执行的时候有自己的环境变量、有自己的工作目录。Runtime和ProcessBuilder提供了不同的方式来启动程序,设置启动参数、环境变量和工作目录。

能够在Java中执行的外部程序,必须是一个实际存在的可执行文件,对于shell下的内嵌命令是不能直接执行的。

采用Runtime的exec执行程序时,首先要使用Runtime的静态方法得到一个Runtime,然后调用Runtime的exec方法。可以将要执行的外部程序和启动参数、环境变量、工作目录作为参数传递给exec方法,该方法执行后返回一个Process代表所执行的程序。

Runtime有六个exec方法,其中两个的定义为:

public Process exec(String[] cmdarray, String[] envp, File dir)

public Process exec(String command, String[] envp, File dir)

cmdarray和command为要执行的命令,可以将命令和参数作为一个字符串command传递给exec()方法,也可以将命令和参数一个一个的方在数组cmdarray里传递给exec()方法。

envp为环境变量,以name=value的形式放在数组中。dir为工作目录。

可以不要dir参数,或者不要envp和dir参数,这样就多出了其它4个exec()方法。如果没有dir参数或者为null,那么新启动的进程就继承当前java进程的工作目录。如果没有envp参数或者为null,那么新启动的进程就继承当前java进程的环境变量。

也可以使用ProcessBuilder类启动一个新的程序,该类是后来添加到JDK中的,而且被推荐使用。通过构造函数设置要执行的命令以及参数,或者也可以通过command()方法获取命令信息后在进行设置。通过directory(File directory) 方法设置工作目录,通过environment()获取环境变量信息来修改环境变量。

在使用ProcessBuilder构造函数创建一个新实例,设置环境变量、工作目录后,可以通过start()方法来启动新程序,与Runtime的exec()方法一样,该方法返回一个Process对象代表启动的程序。

ProcessBuilder与Runtime.exec()方法的不同在于ProcessBuilder提供了redirectErrorStream(boolean redirectErrorStream) 方法,该方法用来将进程的错误输出重定向到标准输出里。即可以将错误输出都将与标准输出合并。

2、Process

不管通过那种方法启动进程后,都会返回一个Process类的实例代表启动的进程,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法:

(1) void destroy()

杀掉子进程。

一般情况下,该方法并不能杀掉已经启动的进程,不用为好。

(2) int exitValue()

返回子进程的出口值。

只有启动的进程执行完成、或者由于异常退出后,exitValue()方法才会有正常的返回值,否则抛出异常。

(3)InputStream getErrorStream()

获取子进程的错误流。

如果错误输出被重定向,则不能从该流中读取错误输出。

(4)InputStream getInputStream()

获取子进程的输入流。

可以从该流中读取进程的标准输出。

(5)OutputStream getOutputStream()

获取子进程的输出流。

写入到该流中的数据作为进程的标准输入。

(6) int waitFor()

导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。

通过该类提供的方法,可以实现与启动的进程之间通信,达到交互的目的。

3、从标准输出和错误输出流读取信息

从启动其他程序的Java进程看,已启动的其他程序输出就是一个普通的输入流,可以通过getInputStream()和getErrorStream来获取。

对于一般输出文本的进程来说,可以将InputStream封装成BufferedReader,然后就可以一行一行的对进程的标准输出进行处理。

4、举例

(1)Runtime.exec()

import java.io.BufferedReader;

import java.io.File;

import java.io.InputStreamReader;

public class Test1 {

public static void main(String[] args) {

try {

Process p = null;

String line = null;

BufferedReader stdout = null;

//list the files and directorys under C:\

p = Runtime.getRuntime().exec("CMD.exe /C dir", null, new File("C:\\"));

stdout = new BufferedReader(new InputStreamReader(p

.getInputStream()));

while ((line = stdout.readLine()) != null) {

System.out.println(line);

}

stdout.close();

//echo the value of NAME

p = Runtime.getRuntime().exec("CMD.exe /C echo %NAME%", new String[] {"NAME=TEST"});

stdout = new BufferedReader(new InputStreamReader(p

.getInputStream()));

while ((line = stdout.readLine()) != null) {

System.out.println(line);

}

stdout.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

(2)ProcessBuilder

import java.io.BufferedReader;

import java.io.File;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.List;

public class Test2 {

public static void main(String[] args) {

try {

List list = new ArrayList();

ProcessBuilder pb = null;

Process p = null;

String line = null;

BufferedReader stdout = null;

//list the files and directorys under C:\

list.add("CMD.EXE");

list.add("/C");

list.add("dir");

pb = new ProcessBuilder(list);

pb.directory(new File("C:\\"));

p = pb.start();

stdout = new BufferedReader(new InputStreamReader(p

.getInputStream()));

while ((line = stdout.readLine()) != null) {

System.out.println(line);

}

stdout.close();

//echo the value of NAME

pb = new ProcessBuilder();

pb.command(new String[] {"CMD.exe", "/C", "echo %NAME%"});

pb.environment().put("NAME", "TEST");

p = pb.start();

stdout = new BufferedReader(new InputStreamReader(p

.getInputStream()));

while ((line = stdout.readLine()) != null) {

System.out.println(line);

}

stdout.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

5、获取进程的返回值

通常,一个程序/进程在执行结束后会向操作系统返回一个整数值,0一般代表执行成功,非0表示执行出现问题。有两种方式可以用来获取进程的返回值。一是利用waitFor(),该方法是阻塞的,执导进程执行完成后再返回。该方法返回一个代表进程返回值的整数值。另一个方法是调用exitValue()方法,该方法是非阻塞的,调用立即返回。但是如果进程没有执行完成,则抛出异常。

6、阻塞的问题

由Process代表的进程在某些平台上有时候并不能很好的工作,特别是在对代表进程的标准输入流、输出流和错误输出进行操作时,如果使用不慎,有可能导致进程阻塞,甚至死锁。

如果将以上事例中的从标准输出重读取信息的语句修改为从错误输出流中读取:

stdout = new BufferedReader(new InputStreamReader(p

.getErrorStream()));

那么程序将发生阻塞,不能执行完成,而是hang在那里。

当进程启动后,就会打开标准输出流和错误输出流准备输出,当进程结束时,就会关闭他们。在以上例子中,错误输出流没有数据要输出,标准输出流中有数据输出。由于标准输出流中的数据没有被读取,进程就不会结束,错误输出流也就不会被关闭,因此在调用readLine()方法时,整个程序就会被阻塞。为了解决这个问题,可以根据输出的实际先后,先读取标准输出流,然后读取错误输出流。

但是,很多时候不能很明确的知道输出的先后,特别是要操作标准输入的时候,情况就会更为复杂。这时候可以采用线程来对标准输出、错误输出和标准输入进行分别处理,根据他们之间在业务逻辑上的关系决定读取那个流或者写入数据。

针对标准输出流和错误输出流所造成的问题,可以使用ProcessBuilder的redirectErrorStream()方法将他们合二为一,这时候只要读取标准输出的数据就可以了。

当在程序中使用Process的waitFor()方法时,特别是在读取之前调用waitFor()方法时,也有可能造成阻塞。可以用线程的方法来解决这个问题,也可以在读取数据后,调用waitFor()方法等待程序结束。

总之,解决阻塞的方法应该有两种:

(1)使用ProcessBuilder类,利用redirectErrorStream方法将标准输出流和错误输出流合二为一,在用start()方法启动进程后,先从标准输出中读取数据,然后调用waitFor()方法等待进程结束。

如:

import java.io.BufferedReader;

import java.io.File;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.List;

public class Test3 {

public static void main(String[] args) {

try {

List list = new ArrayList();

ProcessBuilder pb = null;

Process p = null;

String line = null;

BufferedReader stdout = null;

//list the files and directorys under C:\

list.add("CMD.EXE");

list.add("/C");

list.add("dir1");

pb = new ProcessBuilder(list);

pb.directory(new File("C:\\"));

//merge the error output with the standard output

pb.redirectErrorStream(true);

p = pb.start();

//read the standard output

stdout = new BufferedReader(new InputStreamReader(p

.getInputStream()));

while ((line = stdout.readLine()) != null) {

System.out.println(line);

}

int ret = p.waitFor();

System.out.println("the return code is " + ret);

stdout.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

(2)使用线程

import java.util.*;

import java.io.*;

class StreamWatch extends Thread {

InputStream is;

String type;

List output = new ArrayList();

boolean debug = false;

StreamWatch(InputStream is, String type) {

this(is, type, false);

}

StreamWatch(InputStream is, String type, boolean debug) {

this.is = is;

this.type = type;

this.debug = debug;

}

public void run() {

try {

PrintWriter pw = null;

InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);

String line = null;

while ((line = br.readLine()) != null) {

output.add(line);

if (debug)

System.out.println(type + ">" + line);

}

if (pw != null)

pw.flush();

} catch (IOException ioe) {

ioe.printStackTrace();

}

}

public List getOutput() {

return output;

}

}

public class Test5 {

public static void main(String args[]) {

try {

List list = new ArrayList();

ProcessBuilder pb = null;

Process p = null;

// list the files and directorys under C:\

list.add("CMD.EXE");

list.add("/C");

list.add("dir1");

pb = new ProcessBuilder(list);

pb.directory(new File("C:\\"));

p = pb.start();

// process error and output message

StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),

"ERROR");

StreamWatch outputWatch = new StreamWatch(p.getInputStream(),

"OUTPUT");

// start to watch

errorWatch.start();

outputWatch.start();

//wait for exit

int exitVal = p.waitFor();

//print the content from ERROR and OUTPUT

System.out.println("ERROR: " + errorWatch.getOutput());

System.out.println("OUTPUT: " + outputWatch.getOutput());

System.out.println("the return code is " + exitVal);

} catch (Throwable t) {

t.printStackTrace();

}

}

}

7、在Java中执行Java程序

执行一个Java程序的关键在于:

(1)知道JAVA虚拟机的位置,即java.exe或者java的路径

(2)知道要执行的java程序的位置

(3)知道该程序所依赖的其他类的位置

举一个例子,一目了然。

(1)待执行的Java类

public class MyTest {

public static void main(String[] args) {

System.out.println("OUTPUT one");

System.out.println("OUTPUT two");

System.err.println("ERROR 1");

System.err.println("ERROR 2");

for(int i = 0; i < args.length; i++)

{

System.out.printf("args[%d] = %s.", i, args[i]);

}

}

}

(2)执行该类的程序

import java.util.*;

import java.io.*;

class StreamWatch extends Thread {

InputStream is;

String type;

List output = new ArrayList();

boolean debug = false;

StreamWatch(InputStream is, String type) {

this(is, type, false);

}

StreamWatch(InputStream is, String type, boolean debug) {

this.is = is;

this.type = type;

this.debug = debug;

}

public void run() {

try {

PrintWriter pw = null;

InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);

String line = null;

while ((line = br.readLine()) != null) {

output.add(line);

if (debug)

System.out.println(type + ">" + line);

}

if (pw != null)

pw.flush();

} catch (IOException ioe) {

ioe.printStackTrace();

}

}

public List getOutput() {

return output;

}

}

public class Test6 {

public static void main(String args[]) {

try {

List list = new ArrayList();

ProcessBuilder pb = null;

Process p = null;

String java = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";

String classpath = System.getProperty("java.class.path");

// list the files and directorys under C:\

list.add(java);

list.add("-classpath");

list.add(classpath);

list.add(MyTest.class.getName());

list.add("hello");

list.add("world");

list.add("good better best");

pb = new ProcessBuilder(list);

p = pb.start();

System.out.println(pb.command());

// process error and output message

StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),

"ERROR");

StreamWatch outputWatch = new StreamWatch(p.getInputStream(),

"OUTPUT");

// start to watch

errorWatch.start();

outputWatch.start();

//wait for exit

int exitVal = p.waitFor();

//print the content from ERROR and OUTPUT

System.out.println("ERROR: " + errorWatch.getOutput());

System.out.println("OUTPUT: " + outputWatch.getOutput());

System.out.println("the return code is " + exitVal);

} catch (Throwable t) {

t.printStackTrace();

}

}

}

进程调用进程,会涉及进程之间通信,这个时候可以用socket,jms,文件共享来实现,被调用的进程直接debug比较困难,可以通过打印日志和创建文件,输入输出流,管道来实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432466.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

输入学生成绩,并按升序排列 Ascending.java

import java.util.Arrays;import java.util.Scanner;public class Ascending{ public static void main(String[] args){ Scanner innew Scanner(System.in); int[] arrnew int[10]; for(int i0;i<arr.length;i){ System.out.println("请输入第"(i1)"个学生的…

java判断ftp创建目录是否成功_Java判断Ftp服务器目录是否存在,若不存在创建目录 ....

解决方法1&#xff1a;package com.soft4j.log4j;import java.io.IOException;import sun.net.ftp.FtpClient;public class FtpTest{static String middle_ftpServer "10.103.2.250";static String middle_user "ora9iftp";static String middle_passwor…

第三方静态库的使用

1. 工程根目录下创建文件夹“ThirdParty”&#xff0c;然后在此文件夹下创建“includes”和“libs”文件夹 2. 拷贝静态库的头文件和库文件到上面的文件夹下 3. 修改工程的build.cs文件&#xff0c;增加下面代码1&#xff09;在类中private string ThirdPartyPath { …

UITableView:改变 TableHeaderView 的高度

参考&#xff1a;http://stackoverflow.com/a/526825 有这么一种需求&#xff0c;在列表顶端显示一些别样的数据&#xff0c;而这个别样的数据则需要通过一个别样的 View 来展现&#xff0c;它便是 UITableView 的 tableHeaderView。 倘若 tableHeaderView 里的内容很固定&…

perl 远程 mysql_写的一个perl脚本,用于发送远程MySQL命令 -电脑资料

想写一些简化管理操作的脚本&#xff0c;下面是基础脚本之一&#xff0c;对于一个从来没使用过perl脚本的我来说还是有些难度的&#xff0c;直接上代码。此脚本用于发送远程MySQL命令并且接收结果&#xff0c;功能比较简单&#xff0c;后面会渐渐完善。#!/usr/bin/perl use Get…

【翻译】使用Ext JS设计响应式应用程序

原文&#xff1a;Designing Responsive Applications with Ext JS在当今这个时代&#xff0c;用户都希望Web应用程序无论在形状还是大小上&#xff0c;既能在桌面电脑&#xff0c;也能在移动设备上使用。使应用程序能适应不同的需求渐成趋势。幸运的是&#xff0c;Ext JS 5提供…

java各种的不好_译文《最常见的10种Java异常问题》

封面&#xff1a;洛小汐译者&#xff1a;潘潘知彼知己&#xff0c;方能百战不殆。前言本文总结了有关Java异常的十大常见问题。目录检查型异常(checked) vs. 非检查型异常(Unchecked)异常管理的最佳实践箴言为什么在try代码块中声明的变量不能在catch或者finally中被引用&#…

Hadoop 开源调度系统zeus(二)

紧跟之前Hadoop 开源调度系统zeus(一) 本节主要介绍一下zeus的架构&#xff1a; 先给一个zeus的架构图 无论Master还是Worker都有一套WEB UI&#xff0c;无论从哪个上面去看&#xff0c;看到的结果都是一样的&#xff0c;实际上一般仅仅看主 Master&#xff1a;调度内核&#x…

ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER

该宏非常重要&#xff0c; 其作用是&#xff1a; 创建一个渲染命令任务&#xff0c;并将该任务压入渲染队列&#xff0c;待渲染线程执行. 主要用于多线程渲染&#xff01;#define ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(TypeName,ParamType1,ParamName1,ParamValue1,Code…

python十条建议_十条建议帮你提高Python编程效率

程序员的时间很宝贵&#xff0c;Python这门语言虽然足够简单、优雅&#xff0c;但并不是说你使用Python编程&#xff0c;效率就一定会高。要想节省时间、提高效率&#xff0c;还是需要注意很多地方的。今天就与大家分享资深Python程序员总结的10点建议&#xff0c;帮助大家大幅…

Django:快速搭建简单的Blog

一&#xff0c;创建项目 1, 为blog创建名为mysite的工程项目&#xff1a; django-admin.py startproject mysite2, 项目结构如下&#xff1a; mysite├── manage.py└── mysite├── __init__.py├── settings.py├── urls.py└── wsgi.pymanage.py ----- Django项目…

添加纹理到材质

1. 导入一个图片资源作为纹理贴图 2. 新建一个材质 3. 打开材质编辑器&#xff0c;将“TextureSample”和“TextureCoordinate”两个材质表达式放到蓝图中 4. 设置“TextureSample”的纹理属性为第1步导入的纹理贴图 5. 将“TextureCoordinate”的输出与“TextureSample”的UVs…

c# 路径空格---ProcessStartInfo参数问题

今天在整合程序的时候&#xff0c;要从一个程序转到另一个程序 当然要使用&#xff1a; ProcessStartInfo startInfo new ProcessStartInfo("\\Program Files\\IE\\IE.exe", s); Process.Start(startInfo); 不过对于wm来说 不支持Process.St…

发票 ocr java_OCR识别技术—增值税发票识别

增值税发票识别产品背景在经济活动中产生大量的增值税发票需要进行扫描、数据录入、人工校对等工作。传统的人工录入方式&#xff0c;用户需要投入大量的人力成本和时间成本&#xff0c;不仅抬高了运营成本&#xff0c;而且录入速度难以提升&#xff0c;错误率难以降低&#xf…

java se好用吗_利用 Java SE 7 更好地管理资源

2011 年 5 月发布作者&#xff1a;Julien Ponge本文介绍 Java 7 针对自动资源管理问题给出的解决办法&#xff0c;即 Coin 项目中提出的新语言结构 try-with-resources 语句。&#xff1a;示例源文件 (zip) 简介典型的 Java 应用程序可以处理多种类型的资源&#xff0c;如文件、…

法线贴图Nomal mapping 原理

法线贴图多用在CG动画的渲染以及游戏画面的制作上&#xff0c;将具有高细节的模型通过映射烘焙出法线贴图&#xff0c;贴在低端模型的法线贴图通道上&#xff0c;使之拥有法线贴图的渲染效果&#xff0c;却可以大大降低渲染时需要的面数和计算内容&#xff0c;从而达到优化动画…

Html.Action、html.ActionLink与Url.Action的区别

1.html.ActionLink返回的指向指定controller、指定action的超链接标签<a>标签.如果没有指定controller&#xff0c;则默认为本页面对应的Controller. 如Html.ActionLink(“链接文本”、“someaction”、“somecontroller”,new { id " 123 " },null)生成:<…

ss

http://blog.csdn.net/lvanneo/article/details/16885121 http://www.360doc.com/content/11/0506/22/6110614_114908124.shtml转载于:https://www.cnblogs.com/mliudong/p/3851502.html

gdi+ 双缓冲

内存bmp方式 1. 初始化 Gdiplus::Bitmap* pBitmap new Gdiplus::Bitmap(w,h); Gdiplus::Graphics* pGraphics Gdiplus::Graphics::FromImage(pBitmap); pGraphics->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality); pGraphics->SetInterpolationMode(Gdiplus::In…