本文主要介绍 Java 中关于进程与线程的相关封装类,揭示如何创建 Java 进程与线程,Java 封装类和实际的系统本地进程和线程是如何对应的,以及使用 Java 进程和线程的一些限制。
进程与线程,本质意义上说, 是操作系统的调度单位,可以看成是一种操作系统 “资源” 。Java 作为与平台无关的编程语言,必然会对底层(操作系统)提供的功能进行进一步的封装,以平台无关的编程接口供程序员使用,进程与线程作为操作系统核心概念的一部分无疑亦是如此。在 Java 语言中,对进程和线程的封装,分别提供了 Process 和 ">Thread 相关的一些类。本文首先简单的介绍如何使用这些类来创建进程和线程,然后着重介绍这些类是如何和操作系统本地进程线程相对应的,给出了 Java 虚拟机对于这些封装类的概要性的实现;同时由于 Java 的封装也隐藏了底层的一些概念和可操作性,本文还对 Java 进程线程和本地进程线程做了一些简单的比较,列出了使用 Java 进程、线程的一些限制和需要注意的问题。
Java 进程的建立方法
在 JDK 中,与进程有直接关系的类为 Java.lang.Process,它是一个抽象类。在 JDK 中也提供了一个实现该抽象类的 ProcessImpl 类,如果用户创建了一个进程,那么肯定会伴随着一个新的 ProcessImpl 实例。同时和进程创建密切相关的还有 ProcessBuilder,它是在 JDK1.5 中才开始出现的,相对于 Process 类来说,提供了便捷的配置新建进程的环境,目录以及是否合并错误流和输出流的方式。
Java.lang.Runtime.exec 方法和 Java.lang.ProcessBuilder.start 方法都可以创建一个本地的进程,然后返回代表这个进程的 Java.lang.Process 引用。
Runtime.exec 方法建立一个本地进程
该方法在 JDK1.5 中,可以接受 6 种不同形式的参数传入。
Process exec(String command) Process exec(String [] cmd
array) Process exec(String [] cmdarrag, String [] envp) Process exec(String [] cmdarrag, String [] envp, File dir) Process exec(String cmd, String [] envp) Process exec(String command, String [] envp, File dir)
他们主要的不同在于传入命令参数的形式,提供的环境变量以及定义执行目录。
ProcessBuilder.start 方法来建立一个本地的进程
如果希望在新创建的进程中使用当前的目录和环境变量,则不需要任何配置,直接将命令行和参数传入 ProcessBuilder 中,然后调用 start 方法,就可以获得进程的引用。
Process p = new ProcessBuilder("command", "param").start();
也可以先配置环境变量和工作目录,然后创建进程。
ProcessBuilder pb = new ProcessBuilder("command", "param1", "param2"); Map<String, String> env = pb.environment(); env.put("VAR", "Value"); pb.directory("Dir"); Process p = pb.start();
可以预先配置 ProcessBuilder 的属性是通过 ProcessBuilder 创建进程的最大优点。而且可以在后面的使用中随着需要去改变代码中 pb 变量的属性。如果后续代码修改了其属性,那么会影响到修改后用 start 方法创建的进程,对修改之前创建的进程实例没有影响。
JVM 对进程的实现
在 JDK 的代码中,只提供了 ProcessImpl 类来实现 Process 抽象类。其中引用了 native 的 create, close, waitfor, destory 和 exitValue 方法。在 Java 中,native 方法是依赖于操作系统平台的本地方法,它的实现是用 C++/C++ 等类似的底层语言实现。我们可以在 JVM 的源代码中找到对应的本地方法,然后对其进行分析。JVM 对进程的实现相对比较简单,以 Windows 下的 JVM 为例。在 JVM 中,将 Java 中调用方法时的传入的参数传递给操作系统对应的方法来实现相应的功能。如表 1
表 1. JDK 中 native 方法与 Windows API 的对应关系
JDK 中调用的 native 方法名 对应调用的 Windows API create CreateProcess,CreatePipe close CloseHandle waitfor WaitForMultipleObjects destroy TerminateProcess exitValue GetExitCodeProcess