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

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中,多进程是指在一个程序中启动多个独立的Java虚拟机(JVM)实例,每个实例都可以独立运行自己的任务。这种方式相比于单进程具有以下优势...

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

    Java的多进程运行模式是指在一个Java程序中启动多个独立的Java子进程,每个子进程都有自己的Java虚拟机实例,从而实现程序的并发执行和隔离。这样的设计有助于提高系统的稳定性和可扩展性,因为即使其中一个进程崩溃...

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

    Java程序多进程运行模式的实例分析 Java程序多进程运行模式是指在Java程序中启动多个Java子进程,每个子进程运行在不同的虚拟机进程中,这样可以提高程序的稳定性,因为如果一个子进程发生异常,不会影响其他子进程...

    模拟多进程并发

    在IT领域,多进程并发是操作系统中的核心概念,它指的是在同一时间有多个程序或进程在运行。这种技术被广泛应用于各种软件系统,特别是在资源管理和优化性能方面。在Java编程语言中,虽然Java主要支持线程并发,但也...

    Java 监控 运行时

    综上所述,Java运行时监控涉及多个层面,从内存管理、线程状态到CPU利用率,再到GC行为和自定义监控指标,都需要全面关注。通过有效的监控,我们可以确保Java应用程序的健康运行,提升整体性能和稳定性。

    java多线程设计模式详解

    为了更好地理解和应用这些模式,提供的源码详解文件“java多线程设计模式详解”将详细展示各种模式的实现细节,通过分析源码,读者可以深入掌握Java多线程编程的核心技巧。务必花时间仔细阅读和实践,这对于提升并发...

    Java进程cpu占用率高

    综上所述,解决“Java进程CPU占用率高”问题需要从多个角度出发,包括但不限于代码优化、JVM调优、垃圾收集策略调整、监控与诊断工具的使用等。通过系统性地分析和改进,可以有效地降低Java进程对CPU的占用,提高...

    JConsole(观察分析Java程序的运行)

    ### JConsole:观察与分析Java程序的运行 #### 一、JConsole简介 JConsole是自Java 5开始集成在JDK中的一个强大的性能监视和故障排除工具。它能够帮助开发者和运维人员监控Java应用程序的运行状态,并进行性能分析...

    控制只可以运行单个进程

    而某些配置工具如果多进程运行,可能会导致配置文件的竞态条件,影响系统设置的正确性。因此,很多后台服务、计时任务等都采用单进程设计。 实现单进程的方法有很多种,这里以编程语言Java为例,可以使用以下策略:...

    关于Java的生存现状之分析

    【Java的生存现状分析】 Java 语言,作为程序员和网络工作者的首选,自诞生以来,以其独特的跨平台特性,即“编写一次,到处运行”(Write Once, Run Anywhere),在IT领域内迅速崛起,引领了全球的技术潮流。Java...

    使用JProfiler 6.2 监控本地java程序运行

    然后,JProfiler会自动检测系统上运行的Java进程,从中选择你需要监控的Java应用程序。 步骤三:配置监控参数 在连接对话框中,可以设置监控参数,例如是否开启线程监控、内存分配监控等。这些设置可以根据实际需求...

    JAVA实现多对多聊天

    1. **Java Socket编程**:Socket是网络通信的基础,它提供了进程间通信的能力,使得运行在不同主机上的两个应用程序可以通过网络进行数据交换。在这个聊天系统中,Socket用于创建客户端和服务器端的连接,实现消息的...

    Java最全学习资料+面试题+DOS命令+设计模式+Excel技巧+java学习笔记

    在Java开发中,我们还会用到`javac`(编译Java源码)和`java`(运行编译后的类文件)等与Java相关的DOS命令。 4. **设计模式**:设计模式是软件工程中经过验证的解决方案模板,用于解决常见问题。Java开发者应该...

    JAVA 多线程学习笔记

    在Java编程中,多线程是一项关键技能,它允许程序同时执行多个任务,提升系统效率。这篇学习笔记将深入探讨Java多线程的核心概念、实现方式以及...结合源码分析和实际工具的使用,将使我们成为Java多线程领域的专家。

    java做的教务系统分析

    系统总体结构分析涉及功能分析,系统由一个基础数据管理子系统和多个功能子系统组成。基础数据管理负责处理固定的信息,如学年学期、院系、专业等,而功能子系统则专注于特定的教务任务,如学籍管理、成绩管理等。...

    Java多线程编程深入详解

    标题《Java多线程编程深入详解》所涉及的知识点涵盖了Java多线程编程的核心思想、原理以及在实际开发中可能遇到的问题和解决方案。以下是对这些知识点的详细阐述: 1. 多进程与多线程概念的区分和理解 - 进程是...

    使用java nmon 分析nmon资源

    Java NMON工具的出现,使得用户可以更便捷地处理这些数据,特别是对于那些需要跨多个NMON日志进行比较或需要进行长期趋势分析的场景。它提供了图形化的界面,帮助用户直观地查看资源使用趋势,找出系统瓶颈。此外,...

Global site tag (gtag.js) - Google Analytics