Java的多进程运行模式分析
一般我们在java中运行其它类中的方法时,无论是静态调用,还是动态调用,都是在当前的进程中执行的,也就是说,只有一个java虚拟机实例在运行。而有的时候,我们需要通过java代码启动多个java子进程。这样做虽然占用了一些系统资源,但会使程序更加稳定,因为新启动的程序是在不同的虚拟机进程中运行的,如果有一个进程发生异常,并不影响其它的子进程。
在Java中我们可以使用两种方法来实现这种要求。最简单的方法就是通过Runtime中的exec方法执行java classname。如果执行成功,这个方法返回一个Process对象,如果执行失败,将抛出一个IOException错误。下面让我们来看一个简单的例子。
// Test1.java文件
import java.io.*;
public class Test1 {
public static void main(String[] args) {
FileOutputStream fOut = new FileOutputStream("c:\\Test1.txt");
fOut.close();
System.out.println("被调用成功!");
}
}
// Test_Exec.java
public class Test_Exec {
public static void main(String[] args) {
Runtime run = Runtime.getRuntime();
Process p = run.exec("java test1");
}
}
通过java Test_Exec运行程序后,发现在C盘多了个Test1.txt文件,但在控制台中并未出现"被调用成功!"的输出信息。因此可以断定,Test已经被执行成功,但因为某种原因,Test的输出信息未在Test_Exec的控制台中输出。这个原因也很简单,因为使用exec建立的是Test_Exec的子进程,这个子进程并没有自己的控制台,因此,它并不会输出任何信息。
如果要输出子进程的输出信息,可以通过Process中的getInputStream得到子进程的输出流(在子进程中输出,在父进程中就是输入),然后将子进程中的输出流从父进程的控制台输出。具体的实现代码如下如示:
// Test_Exec_Out.java
import java.io.*;
public class Test_Exec_Out {
public static void main(String[] args) {
Runtime run = Runtime.getRuntime();
Process p = run.exec("java test1");
BufferedInputStream in = new BufferedInputStream(p.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String s;
while ((s = br.readLine()) != null)
System.out.println(s);
}
}
从上面的代码可以看出,在Test_Exec_Out.java中通过按行读取子进程的输出信息,然后在Test_Exec_Out中按每行进行输出。 上面讨论的是如何得到子进程的输出信息。那么,除了输出信息,还有输入信息。既然子进程没有自己的控制台,那么输入信息也得由父进程提供。我们可以通过Process的getOutputStream方法来为子进程提供输入信息(即由父进程向子进程输入信息,而不是由控制台输入信息)。我们可以看看如下的代码:
// Test2.java文件
import java.io.*;
public class Test2{
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("由父进程输入的信息:" + br.readLine());
}
}
// Test_Exec_In.java
import java.io.*;
public class Test_Exec_In {
public static void main(String[] args) {
Runtime run = Runtime.getRuntime();
Process p = run.exec("java test2");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
bw.write("向子进程输出信息");
bw.flush();
bw.close(); // 必须得关闭流,否则无法向子进程中输入信息
// System.in.read();
}
}
从以上代码可以看出,Test1得到由Test_Exec_In发过来的信息,并将其输出。当你不加bw.flash()和bw.close()时,信息将无法到达子进程,也就是说子进程进入阻塞状态,但由于父进程已经退出了,因此,子进程也跟着退出了。如果要证明这一点,可以在最后加上System.in.read(),然后通过任务管理器(在windows下)查看java进程,你会发现如果加上bw.flush()和bw.close(),只有一个java进程存在,如果去掉它们,就有两个java进程存在。这是因为,如果将信息传给Test2,在得到信息后,Test2就退出了,而如果不用flush(),只有当缓冲区满的时候再回发送数据。在这里有一点需要说明一下,exec的执行是异步的,并不会因为执行的某个程序阻塞而停止执行下面的代码。因此,可以在运行test2后,仍可以执行下面的代码。
exec方法经过了多次的重载。上面使用的只是它的一种重载。它还可以将命令和参数分开,如exec("java.test2")可以写成exec("java", "test2")。exec还可以通过指定的环境变量运行不同配置的java虚拟机。
除了使用Runtime的exec方法建立子进程外,还可以通过ProcessBuilder建立子进程。访问平台专有信息并不是一件容易的事。虽然可以使用 Runtime.exec() 创建进程,但由于平台之间的差异,构造参数集常常令人头痛不已。Tiger提供了新的ProcessBuilder类,使得访问平台专有信息更加容易。
ProcessBuilder的使用方法如下:
// Test_Exec_Out.java
import java.io.*;
public class Test_Exec_Out {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("java", "test1");
Process p = pb.start();
… …
}
}
在建立子进程上,ProcessBuilder和Runtime类似,不同的ProcessBuilder使用start()方法启动子进程,而Runtime使用exec方法启动子进程。得到Process后,它们的操作就完全一样的。
ProcessBuilder和Runtime一样,也可设置可执行文件的环境信息、工作目录等。下面的例子描述了如何使用ProcessBuilder设置这些信息。
ProcessBuilder pb = new ProcessBuilder("Command", "arg2", "arg2", ''');
// 设置环境变量
Map< String, String > env = pb.environment();
env.put("key1", "value1");
env.remove("key2");
env.put("key2", env.get("key1") + "_test");
pb.directory("..\abcd"); // 设置工作目录
Process p = pb.start(); // 建立子进程
关于工作路径:
假定在/bin下面有个可执行文件xxx,
我在shell里cd /home/abc,然后/bin/xxx来调用他,那么当前工作目录就是/home/abc
这时候fopen("a.txt", "r"),就是在/home/abc来找这个a.txt文件。
如果在执行过程中调用chdir("/home/abc/def")成功切换了目录,那么当前工作目录就变成了/home/abc/def
这时候fopen("a.txt", "r"),就是在/home/abc/def来找这个a.txt文件。
可以用:
System.getProperty( "java.class.path ");
或者
System.getProperty( "user.dir ");
发表评论
-
java面试总结(1)——基础知识
2012-07-05 15:54 8661、什么是多态? 多态,父类的引用指向子类的对象,使父类的引 ... -
递归-组合(用背包问题解)
2011-04-01 21:23 748求指定数据的组合,这里的指定数据用一个数组模拟所有可以选择 ... -
Servlet和JSP的线程安全问题
2011-03-25 10:50 773不要定义servlet的类变量,不要使用jsp中的s ... -
Java同步机制浅谈―synchronized
2011-03-25 10:20 989Java对多线程的支持 ... -
代码复用的规则
2011-03-24 17:25 650李炜 北京杰合伟业软件公司产品技术部经理2001 年 7 ... -
用JSP实现假分页
2008-08-08 10:29 7361.使用MySql数据库建一个表,并添加记录: -- 删除表 ... -
用MVC模式实现真分页
2008-08-23 21:01 524·我们在之前代码上实现一个搜索框 输入查询关键字:< ... -
位运算符
2008-08-24 19:35 339Java 定义的位运算(bitwise operators ) ... -
struts高级技术——解决重复提交和上传文件
2008-08-24 19:44 433·解决重复提交的工具——Token令牌<?xml:nam ... -
从class.forName()说java中的reflection(反射/映像)
2008-09-21 21:19 530先通过我们一个熟悉的例子来说明: 使用JDBC时,我们都会很 ... -
eclipse 自动补全的设置,不用按 alt-/ 了
2011-03-23 11:07 701偶然间看到了这个,或许有和我一样不喜欢按 alt-/ 兄弟用得 ... -
用JSP实现假分页
2008-08-08 10:29 13441.使用MySql数据库建一个表,并添加记录: -- 删除表 ... -
用MVC模式实现真分页
2008-08-23 21:01 1154·我们在之前代码上实现一个搜索框 输入查询关键字:< ... -
位运算符
2008-08-24 19:35 751Java 定义的位运算(bitwise operators ) ... -
java排序大全
2008-08-24 19:42 648java排序大全 插入排序: packag ... -
struts高级技术——解决重复提交和上传文件
2008-08-24 19:44 840·解决重复提交的工具——Token令牌<?xml:nam ... -
从class.forName()说java中的reflection(反射/映像)
2008-09-21 21:19 904先通过我们一个熟悉的例子来说明: 使用JDBC时,我们都会很 ...
相关推荐
功能:获取java进程pid 进程可根据该pid调用exec自杀 注意事项:不能改变PidTool.java所在的包,否则需要重行生成dll。 编译命令中 "-PidTool.dll" 改为 "-FePidTool.dll",我整漏了! 使用方法: 1.javac PidTool...
java多进程并发 读文件 测试代码,适合初学并发控制 的同学
实现Java通过进程名称杀进程,列子中主要实现在windows操作系统中,将进程名称为java-test.exe的进程kill掉。
有时候我们需要通过java代码启动多个java子进程。这样做虽然占用了一些系统资源,但会使程序更加稳定,因为新启动的程序是在不同的虚拟机进程中运行的,如果有一个进程发生异常,并不影响其它的子进程。在Java中我们...
java创建进程,及根据命令行、pid删除进程
主要介绍了详解Java中多进程编程的实现,和多线程一样,多进程同样是实现并发的一种方式,需要的朋友可以参考下
TensorRT python多进程推理踩坑(csdn)————程序
java通过sigar获取进程的相关信息 ,包含各个进程的PID、名称、CPU使用率、所占内存大小等
进程监视——Process Monitor V2.02 彩虹神话汉化绿色版 此软件由微软开发,极适合windows上运行 使用也方便,完全绿色,不需安装。
本人写了一个java进程通信的工具jar,方便大家简单的使用java进程通信。 开启守护进程,获取消息: package com.test; import org.msun.process.ProcessMonitor; import org.msun.process.ProcessMonitor....
使用这个程序可以轻易关闭著名杀毒软件、系统关键进程,但使用前请关闭杀毒软件&防火墙,以免误杀。
我国电子信息制造业的创新转型进程——基于行业授权专利的考察.pdf
深入推动档案数字化进程 ——国内数字档案馆的发展现状及趋势探究.pdf
Process Explorer 是一款免费的增强型任务管理器,是最好的进程管理器. 它能让使用者了解看不到的在后台执行的处理程序,可以使用它方便地管理你的程序进程. 能监视,挂起,重启,强行终止任何程序,包括系统级别的不允许...
java 获取指定java 获取指定的进程id的进程id
课时跟踪检测(三十五)区域工业化与城市化进程——以珠江三角洲为例.doc
系统组织 整体推进 加速LED产业创新进程——中科院半导体照明产业科技成果对接会在扬州成功举办.pdf
JakeWharton最新力作——Process Phoenix,重启application process.zip,凤凰进程有助于重新启动您的应用程序进程。