`
yangyiqian
  • 浏览: 114581 次
  • 来自: ...
社区版块
存档分类
最新评论

Java的多进程运行模式分析

    博客分类:
  • JAVA
阅读更多
一般我们在Java中运行其它类中的方法时,无论是静态调用,还是动态调用,都是在当前的进程中执行的,也就是说,只有一个Java虚拟机实例在运行。而有的时候,我们需要通过Java代码启动多个Java子进程。这样做虽然占用了一些系统资源,但会使程序更加稳定,因为新启动的程序是在不同的虚拟机进程中运行的,如果有一个进程发生异常,并不影响其它的子进程。

在Java中我们可以使用两种方法来实现这种要求。最简单的方法就是通过Runtime中的exec方法执行Java classname。如果执行成功,这个方法返回一个Process对象,如果执行失败,将抛出一个IOException错误。下面让我们来看一个简单的例子。

// Test1.java文件
import java.io.*;
public class Test
{
 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 Test
{
 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就退出了。在这里有一点需要说明一下,exec的执行是异步的,并不会因为执行的某个程序阻塞而停止执行下面的代码。因此,可以在运行 test2后,仍可以执行下面的代码。

exec方法经过了多次的重载。上面使用的只是它的一种重载。它还可以将命令和参数分开,如exec("Java.test2")可以写成exec("Java", "test2")。exec还可以通过指定的环境变量运行不同配置的Java虚拟机。

除了使用Runtime的exec方法建立子进程外,还可以通过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 env = pb.environment();
env.put("key1", "value1");
env.remove("key2");
env.put("key2", env.get("key1") + "_test"); 
pb.directory("..abcd"); // 设置工作目录
Process p = pb.start(); // 建立子进程 
分享到:
评论
1 楼 t8500071 2010-10-09  
原来exec后是子进程,怪不得我怎么看都不像是一个完全独立的进程。

相关推荐

    Java程序多进程运行模式的实例分析

    Java程序多进程运行模式的实例分析,实现进程管理。

    Java的多进程运行模式分析与编程[收集].pdf

    Java的多进程运行模式分析与编程[收集].pdf

    Java程序多进程运行模式的实例分析.pdf

    Java程序多进程运行模式的实例分析.pdf

    JAVA上百实例源码以及开源项目

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    JAVA上百实例源码以及开源项目源代码

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    JAVA基础课程讲义

    Java运行时环境JRE(Java Runtime Environment) 17 JAVA语言应用范围 18 第一个JAVA程序 18 JAVA开发环境搭建 18 一个典型的JAVA程序的编写和运行过程 19 第一个程序常见错误 20 第一个JAVA程序的总结和提升 20 常用...

    java 面试题 总结

    方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数...

    java基础案例与开发详解案例源码全

    2.6 Java技术两种核心运行机制29 2.7 上机练习30 第3章 3.1 变量32 3.1.1 什么是变量32 3.1.2 为什么需要变量32 3.1.3 变量的声明和赋值33 3.1.4 变量应用实例33 3.2 数据的分类34 3.2.1 Java中的八种基本数据类型34...

    java范例开发大全

    实例279 一对多通信模式 544 实例280 自制浏览器 549 实例281 扫描TCP端口 551 实例282 TCP协议服务器 552 实例283 TCP协议客户机 553 实例284 Socket连接信息 555 实例285 Echo服务的客户端是如何实现的? 556 实例...

    java范例开发大全源代码

    第1篇 Java编程基础  第1章 Java开发环境的搭建(教学视频:9分钟) 2  1.1 理解Java 2  1.2 搭建Java所需环境 3  1.2.1 下载JDK 3  1.2.2 安装JDK 4  1.2.3 配置环境 5  1.2.4 测试JDK配置...

    Java并发编程(学习笔记).xmind

    进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 (2)建模简单:通过使用线程可以讲复杂并且...

    Java范例开发大全 (源程序)

     实例214 模拟操作系统的进程调度 379  实例215 利用栈将字符串逆序输出 381  实例216 动态的数组链表 382  实例217 你能猜出鱼是谁的宠物吗? 387  实例218 使用Collections类对List的排序操作 393  ...

    超级有影响力霸气的Java面试题大全文档

     方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和...

    Java范例开发大全(全书源程序)

    Java范例开发大全(全书源程序),目录如下: 第1篇 Java编程基础 第1章 Java开发环境的搭建(教学视频:9分钟) 2 1.1 理解Java 2 1.2 搭建Java所需环境 3 1.2.1 下载JDK 3 1.2.2 安装JDK 4 1.2.3 配置环境...

    JAVA程序设计教程

    1.3.3 Java程序的运行 ............................................................................................10 1.3.4 Java程序的调试 .............................................................

    java范例开发大全(pdf&源码)

    实例214 模拟操作系统的进程调度 379 实例215 利用栈将字符串逆序输出 381 实例216 动态的数组链表 382 实例217 你能猜出鱼是谁的宠物吗? 387 实例218 使用Collections类对List的排序操作 393 实例219 LinkedList的...

    基于Java的校园水电管理系统的设计与实现.txt

    也就是要将水电管理的各项数据,如统计信息、维修信息、收费信息等在收录、存档、报表分析、交流等方面实行计算机网络化运行,为高校水电管理工作提供优质高效、可靠、实用、及时、准确的信息支持和信息服务,以全面...

    JAVA核心知识点整理(有效)

    可达性分析............................................................................................................................................... 26 2.3.2. 2.3.3. 老年代 ........................

Global site tag (gtag.js) - Google Analytics