- 浏览: 263360 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (88)
- JAVA / base (26)
- JAVA / web (12)
- JAVA / Lib-tools (5)
- SERVER / tomcat (4)
- DB / mysql (4)
- DB / mongodb (2)
- DB / memcached (2)
- DB / redis (2)
- WEB / Front-end (3)
- WEB / security (4)
- WEB / css (2)
- WEB / js (4)
- OS / linux (3)
- IT / Architecture (4)
- IT / other (2)
- Android (9)
- Go (1)
- Other (1)
- OS / Mac (2)
最新评论
-
Zero2Max:
哈哈,马士兵老师也发现了。
java实现接口的bug -
xly1981:
能像CSRF攻击一样带个图就更棒了
XSS跨站攻击 -
xmong:
df274119386 写道在javascript中看到下面的 ...
CSRF攻击与防御策略 -
df274119386:
在javascript中看到下面的语句 e.value = t ...
CSRF攻击与防御策略 -
xmong:
yzxqml 写道xmong 写道yzxqml 写道tomca ...
Tomcat集群
Java创建进程
1 进程的概念 1
1.1 进程的概念 1
1.2 进程的特征 1
1.3 进程与线程区别 1
2 进程的创建 1
2.1 JAVA进程的创建 1
2.1.1 ProcessBuilder 2
2.1.2 Runtime 3
2.1.3 Process 4
2.2 实例 5
2.2.1 创建子进程 5
2.2.2 进程阻塞问题 7
2.2.3 在java中执行java程序 11
1 进程的概念
1.1 进程的概念
进程是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。
第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
第 二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。
1.2 进程的特征
动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
结构特征:进程由程序、数据和进程控制块三部分组成。
多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。
1.3 进程与线程区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影 响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程 序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进 程。
2 进程的创建
2.1 Java进程的创建
Java提供了两种方法用来启动进程或其它程序:
(1)使用Runtime的exec()方法
(2)使用ProcessBuilder的start()方法
2.1.1 ProcessBuilder
ProcessBuilder类是J2SE 1.5在java.lang中新添加的一个新类,此类用于创建操作系统进程,它提供一种启动和管理进程(也就是应用程序)的方法。在J2SE 1.5之前,都是由Process类处来实现进程的控制管理。
每个 ProcessBuilder 实例管理一个进程属性集。start() 方法利用这些属性创建一个新的 Process 实例。start() 方法可以从同一实例重复调用,以利用相同的或相关的属性创建新的子进程。
每个进程生成器管理这些进程属性:
命令 是一个字符串列表,它表示要调用的外部程序文件及其参数(如果有)。在此,表示有效的操作系统命令的字符串列表是依赖于系统的。例如,每一个总体变量,通常都要成为此列表中的元素,但有一些操作系统,希望程序能自己标记命令行字符串——在这种系统中,Java 实现可能需要命令确切地包含这两个元素。
环境 是从变量 到值 的依赖于系统的映射。初始值是当前进程环境的一个副本(请参阅 System.getenv())。
工作目录。默认值是当前进程的当前工作目录,通常根据系统属性 user.dir 来命名。
redirectErrorStream 属性。最初,此属性为 false,意思是子进程的标准输出和错误输出被发送给两个独立的流,这些流可以通过 Process.getInputStream() 和 Process.getErrorStream() 方法来访问。如果将值设置为 true,标准错误将与标准输出合并。这使得关联错误消息和相应的输出变得更容易。在此情况下,合并的数据可从 Process.getInputStream() 返回的流读取,而从 Process.getErrorStream() 返回的流读取将直接到达文件尾。
修改进程构建器的属性将影响后续由该对象的 start() 方法启动的进程,但从不会影响以前启动的进程或 Java 自身的进程。大多数错误检查由 start() 方法执行。可以修改对象的状态,但这样 start() 将会失败。例如,将命令属性设置为一个空列表将不会抛出异常,除非包含了 start()。
注意,此类不是同步的。如果多个线程同时访问一个 ProcessBuilder,而其中至少一个线程从结构上修改了其中一个属性,它必须 保持外部同步。
2.1.2 Runtime
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
应用程序不能创建自己的 Runtime 类实例。但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用。一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为。
2.1.3 Process
不管通过那种方法启动进程后,都会返回一个Process类的实例代表启动的进程,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法:
通过该类提供的方法,可以实现与启动的进程之间通信,达到交互的目的。
2.2 实例
2.2.1 创建子进程
要创建子进程可以通过使用使用ProcessBuilder的start()方法和Runtime的exec()方法。
(1)Runtime.exec()
(2)ProcessBuilder
从启动其他程序的Java进程看,已启动的其他程序输出就是一个普通的输入流,可以通过getInputStream()和getErrorStream来获取。对于一般输出文本的进程来说,可以将InputStream封装成BufferedReader,然后就可以一行一行的对进程的标准输出进行处理。
通常,一个程序/进程在执行结束后会向操作系统返回一个整数值,0一般代表执行成功,非0表示执行出现问题。有两种方式可以用来获取进程的返回值。一是利用waitFor(),该方法是阻塞的,执导进程执行完成后再返回。该方法返回一个代表进程返回值的整数值。另一个方法是调用exitValue()方法,该方法是非阻塞的,调用立即返回。但是如果进程没有执行完成,则抛出异常。
2.2.2 进程阻塞问题
由Process代表的进程在某些平台上有时候并不能很好的工作,特别是在对代表进程的标准输入流、输出流和错误输出进行操作时,如果使用不慎,有可能导致进程阻塞,甚至死锁。
如果将以上事例中的从标准输出重读取信息的语句修改为从错误输出流中读取:
stdout = new BufferedReader(new InputStreamReader(p.getErrorStream()));
那么程序将发生阻塞,不能执行完成,而是hang在那里。
当进程启动后,就会打开标准输出流和错误输出流准备输出,当进程结束时,就会关闭他们。在以上例子中,错误输出流没有数据要输出,标准输出流中有数据输出。由于标准输出流中的数据没有被读取,进程就不会结束,错误输出流也就不会被关闭,因此在调用readLine()方法时,整个程序就会被阻塞。为了解决这个问题,可以根据输出的实际先后,先读取标准输出流,然后读取错误输出流。
但是,很多时候不能很明确的知道输出的先后,特别是要操作标准输入的时候,情况就会更为复杂。这时候可以采用线程来对标准输出、错误输出和标准输入进行分别处理,根据他们之间在业务逻辑上的关系决定读取那个流或者写入数据。
针对标准输出流和错误输出流所造成的问题,可以使用ProcessBuilder的redirectErrorStream()方法将他们合二为一,这时候只要读取标准输出的数据就可以了。
当在程序中使用Process的waitFor()方法时,特别是在读取之前调用waitFor()方法时,也有可能造成阻塞。可以用线程的方法来解决这个问题,也可以在读取数据后,调用waitFor()方法等待程序结束。
总之,解决阻塞的方法应该有两种:
(1)使用ProcessBuilder类,利用redirectErrorStream方法将标准输出流和错误输出流合二为一,在用start()方法启动进程后,先从标准输出中读取数据,然后调用waitFor()方法等待进程结束。
如:
(2)使用线程
2.2.3 在java中执行java程序
执行一个Java程序的关键在于:
(1)知道JAVA虚拟机的位置,即java.exe或者java的路径
(2)知道要执行的java程序的位置
(3)知道该程序所依赖的其他类的位置
举一个例子,一目了然。
(1)待执行的Java类
(2)执行该类的程序
/****************/
未完待续
1 进程的概念 1
1.1 进程的概念 1
1.2 进程的特征 1
1.3 进程与线程区别 1
2 进程的创建 1
2.1 JAVA进程的创建 1
2.1.1 ProcessBuilder 2
2.1.2 Runtime 3
2.1.3 Process 4
2.2 实例 5
2.2.1 创建子进程 5
2.2.2 进程阻塞问题 7
2.2.3 在java中执行java程序 11
1 进程的概念
1.1 进程的概念
进程是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。
第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
第 二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。
1.2 进程的特征
动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
结构特征:进程由程序、数据和进程控制块三部分组成。
多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。
1.3 进程与线程区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影 响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程 序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进 程。
2 进程的创建
2.1 Java进程的创建
Java提供了两种方法用来启动进程或其它程序:
(1)使用Runtime的exec()方法
(2)使用ProcessBuilder的start()方法
2.1.1 ProcessBuilder
ProcessBuilder类是J2SE 1.5在java.lang中新添加的一个新类,此类用于创建操作系统进程,它提供一种启动和管理进程(也就是应用程序)的方法。在J2SE 1.5之前,都是由Process类处来实现进程的控制管理。
每个 ProcessBuilder 实例管理一个进程属性集。start() 方法利用这些属性创建一个新的 Process 实例。start() 方法可以从同一实例重复调用,以利用相同的或相关的属性创建新的子进程。
每个进程生成器管理这些进程属性:
命令 是一个字符串列表,它表示要调用的外部程序文件及其参数(如果有)。在此,表示有效的操作系统命令的字符串列表是依赖于系统的。例如,每一个总体变量,通常都要成为此列表中的元素,但有一些操作系统,希望程序能自己标记命令行字符串——在这种系统中,Java 实现可能需要命令确切地包含这两个元素。
环境 是从变量 到值 的依赖于系统的映射。初始值是当前进程环境的一个副本(请参阅 System.getenv())。
工作目录。默认值是当前进程的当前工作目录,通常根据系统属性 user.dir 来命名。
redirectErrorStream 属性。最初,此属性为 false,意思是子进程的标准输出和错误输出被发送给两个独立的流,这些流可以通过 Process.getInputStream() 和 Process.getErrorStream() 方法来访问。如果将值设置为 true,标准错误将与标准输出合并。这使得关联错误消息和相应的输出变得更容易。在此情况下,合并的数据可从 Process.getInputStream() 返回的流读取,而从 Process.getErrorStream() 返回的流读取将直接到达文件尾。
修改进程构建器的属性将影响后续由该对象的 start() 方法启动的进程,但从不会影响以前启动的进程或 Java 自身的进程。大多数错误检查由 start() 方法执行。可以修改对象的状态,但这样 start() 将会失败。例如,将命令属性设置为一个空列表将不会抛出异常,除非包含了 start()。
注意,此类不是同步的。如果多个线程同时访问一个 ProcessBuilder,而其中至少一个线程从结构上修改了其中一个属性,它必须 保持外部同步。
构造方法摘要 ProcessBuilder(List<String> command) 利用指定的操作系统程序和参数构造一个进程生成器。 ProcessBuilder(String... command) 利用指定的操作系统程序和参数构造一个进程生成器。 方法摘要 List<String> command() 返回此进程生成器的操作系统程序和参数。 ProcessBuilder command(List<String> command) 设置此进程生成器的操作系统程序和参数。 ProcessBuilder command(String... command) 设置此进程生成器的操作系统程序和参数。 File directory() 返回此进程生成器的工作目录。 ProcessBuilder directory(File directory) 设置此进程生成器的工作目录。 Map<String,String> environment() 返回此进程生成器环境的字符串映射视图。 boolean redirectErrorStream() 通知进程生成器是否合并标准错误和标准输出。 ProcessBuilder redirectErrorStream(boolean redirectErrorStream) 设置此进程生成器的 redirectErrorStream 属性。 Process start() 使用此进程生成器的属性启动一个新进程。
2.1.2 Runtime
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
应用程序不能创建自己的 Runtime 类实例。但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用。一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为。
void addShutdownHook(Thread hook) 注册新的虚拟机来关闭挂钩。 int availableProcessors() 向 Java 虚拟机返回可用处理器的数目。 Process exec(String command) 在单独的进程中执行指定的字符串命令。 Process exec(String[] cmdarray) 在单独的进程中执行指定命令和变量。 Process exec(String[] cmdarray, String[] envp) 在指定环境的独立进程中执行指定命令和变量。 Process exec(String[] cmdarray, String[] envp, File dir) 在指定环境和工作目录的独立进程中执行指定的命令和变量。 Process exec(String command, String[] envp) 在指定环境的单独进程中执行指定的字符串命令。 Process exec(String command, String[] envp, File dir) 在有指定环境和工作目录的独立进程中执行指定的字符串命令。 void exit(int status) 通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。 long freeMemory() 返回 Java 虚拟机中的空闲内存量。 void gc() 运行垃圾回收器。 InputStream getLocalizedInputStream(InputStream in) 已过时。 从 JDK 1.1 开始,将本地编码字节流转换为 Unicode 字符流的首选方法是使用 InputStreamReader 和 BufferedReader 类。 OutputStream getLocalizedOutputStream(OutputStream out) 已过时。 从 JDK 1.1 开始,将 Unicode 字符流转换为本地编码字节流的首选方法是使用 OutputStreamWriter、BufferedWriter 和 PrintWriter 类。 static Runtime getRuntime() 返回与当前 Java 应用程序相关的运行时对象。 void halt(int status) 强行终止目前正在运行的 Java 虚拟机。 void load(String filename) 加载作为动态库的指定文件名。 void loadLibrary(String libname) 加载具有指定库名的动态库。 long maxMemory() 返回 Java 虚拟机试图使用的最大内存量。 boolean removeShutdownHook(Thread hook) 取消注册某个先前已注册的虚拟机关闭挂钩。 void runFinalization() 运行挂起 finalization 的所有对象的终止方法。 static void runFinalizersOnExit(boolean value) 已过时。 此方法本身具有不安全性。它可能对正在使用的对象调用终结方法,而其他线程正在操作这些对象,从而导致不正确的行为或死锁。 long totalMemory() 返回 Java 虚拟机中的内存总量。 void traceInstructions(boolean on) 启用/禁用指令跟踪。 void traceMethodCalls(boolean on) 启用/禁用方法调用跟踪。
2.1.3 Process
不管通过那种方法启动进程后,都会返回一个Process类的实例代表启动的进程,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法:
void destroy() 杀掉子进程。 一般情况下,该方法并不能杀掉已经启动的进程,不用为好。 int exitValue() 返回子进程的出口值。 只有启动的进程执行完成、或者由于异常退出后,exitValue()方法才会有正常的返回值,否则抛出异常。 InputStream getErrorStream() 获取子进程的错误流。 如果错误输出被重定向,则不能从该流中读取错误输出。 InputStream getInputStream() 获取子进程的输入流。 可以从该流中读取进程的标准输出。 OutputStream getOutputStream() 获取子进程的输出流。 写入到该流中的数据作为进程的标准输入。 int waitFor() 导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
通过该类提供的方法,可以实现与启动的进程之间通信,达到交互的目的。
2.2 实例
2.2.1 创建子进程
要创建子进程可以通过使用使用ProcessBuilder的start()方法和Runtime的exec()方法。
(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<String> list = new ArrayList<String>(); 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(); } }
从启动其他程序的Java进程看,已启动的其他程序输出就是一个普通的输入流,可以通过getInputStream()和getErrorStream来获取。对于一般输出文本的进程来说,可以将InputStream封装成BufferedReader,然后就可以一行一行的对进程的标准输出进行处理。
通常,一个程序/进程在执行结束后会向操作系统返回一个整数值,0一般代表执行成功,非0表示执行出现问题。有两种方式可以用来获取进程的返回值。一是利用waitFor(),该方法是阻塞的,执导进程执行完成后再返回。该方法返回一个代表进程返回值的整数值。另一个方法是调用exitValue()方法,该方法是非阻塞的,调用立即返回。但是如果进程没有执行完成,则抛出异常。
2.2.2 进程阻塞问题
由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<String> list = new ArrayList<String>(); 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<String> output = new ArrayList<String>(); 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<String> getOutput() { return output; } }
public class Test5 { public static void main(String args[]) { try { List<String> list = new ArrayList<String>(); 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(); } } }
2.2.3 在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<String> output = new ArrayList<String>(); 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<String> getOutput() { return output; } }
public class Test6 { public static void main(String args[]) { try { List<String> list = new ArrayList<String>(); 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(); }
/****************/
未完待续
发表评论
-
Java validation(java验证器实现)
2014-03-18 11:45 3699Java validation 1. java验证器 在 ... -
Memo class备注类信息
2014-03-18 09:52 891Memo Class 1. 什么是Memo Class Mem ... -
java annotation注解
2014-01-24 18:01 9501. Annotation的声明方式 An ... -
Java RMI
2013-03-28 15:12 1731Java Rmi 目录 1 JAVA RMI 1 ... -
java内部类
2013-03-19 16:25 1046Java内部类 目录 1 JAVA ... -
java多线程设计模式之订单模式
2013-03-11 14:00 2694Java多线程实现订单模式: 客户端线程向服务端发起请求后, ... -
java多线程设计模式之线程池处理请求
2013-03-08 17:50 1826Java实现线程池处理请求: 客户端线程发出请求,请求存入请 ... -
java多线程设计模式之异步处理请求
2013-03-08 12:36 4527Java实现多线程异步处理请求: Java实现多线程异步处理 ... -
java多线程设计模式之读写文件模式
2013-03-07 17:56 1589Java实现多线程读写数据 ... -
java多线程设计模式之生产者与消费者
2013-03-07 11:34 1067Java实现多线程生产者与消费者: 生产者线程负责生产产品 ... -
java多线程设计模式之文件保存
2013-03-06 16:16 1612Java实现多线程保存文件:两线程去保存文件,一个保存线程定时 ... -
java多线程设计模式之队列通信
2013-03-06 13:51 2494Java实现多线程处理队列请求通信:客户端线程向请求队列中不断 ... -
Java读linux系统文件文件名乱码
2012-12-06 17:01 91661,问题描述 web应用想通过Java读取linux系统文件显 ... -
Java安全加密
2012-11-28 10:24 1989安全加密 目录 1 加密安全 1 1.1 应用的安全 1 ... -
图着色问题
2012-11-27 13:05 3124图着色问题 目录 1 图 ... -
JDK6新特性
2012-07-03 23:24 2902JDK6的新特性 JDK6的新特性之一_Desktop类 ... -
JDK7新特性
2012-07-03 15:39 3514JDK7新特性 一 JDK7新特性简介 准备 JDK7下载 ... -
JDK5新特性
2012-07-03 10:23 73JDK5.0新特性 1.自动封箱和自动解封(简单类型和封装类 ... -
java多线程
2012-06-15 15:12 1574Java多线程 目录 1 线 ... -
代理模式
2012-06-13 14:12 1385代理模式 目录 1 代理 ...
相关推荐
本篇文章将详细探讨如何使用Java创建进程,以及如何根据命令行参数和进程ID(PID)来删除进程。 首先,我们来看如何在Java中创建一个进程。`ProcessBuilder`类是创建新进程的主要工具。下面是一个简单的示例: ```...
使用Idea创建项目,创建进程并在控制台显示机器当前IP信息
Java进程间的管道通信是一种进程间通信(IPC,Inter-Process Communication)的方式,它允许不同的Java进程之间通过共享的管道进行数据传输。虽然Java标准库不直接支持创建管道文件,但可以借助于操作系统提供的功能...
在Java编程环境中,实现守护进程(Daemon)以及创建多个进程和JVM是非常常见的需求,特别是在构建分布式系统或者需要持续后台运行的服务时。本篇将详细阐述如何使用Java来实现这些功能。 守护进程通常是一个在后台...
### Java通过Sigar库获取进程相关信息 在Java开发过程中,有时候我们需要监控系统资源或特定进程的状态,例如CPU使用率、内存占用情况等。这在服务器性能监控、问题排查等方面尤为重要。本文将详细介绍如何使用...
在Java中,最常见的方式是通过创建线程来实现后台进程。Java语言提供了Thread类,我们可以自定义Thread子类并重写run()方法,这样当线程启动时,就会执行run()中的代码。例如: ```java class BackgroundTask ...
Java中进程与线程_三种实现方式总结 Java中进程与线程是两个非常重要的概念,理解它们之间的关系和区别是非常必要的。在 Java 中,进程和线程都是程序执行的基本单位,但它们有着不同的特点和应用场景。 进程是指...
首先,Java提供了两种方法来创建进程:通过`Runtime.exec()`方法和`ProcessBuilder.start()`方法。 1. **ProcessBuilder类** - `ProcessBuilder`是自Java 1.5版本起引入的新类,用于创建和管理操作系统进程。这个...
Java作为一种强大的多线程编程语言,提供了丰富的API来支持进程同步。本篇文章将深入探讨如何使用Java实现“生产者-消费者”问题的进程同步。 生产者-消费者问题是多线程设计模式中的一个经典案例,它模拟了两个...
在Java中实现这一算法,可以创建一个进程队列,每个进程对象包含其优先级属性。调度器遍历队列,选择优先级最高的进程进行执行。当有新进程加入或优先级发生变化时,需要更新队列排序。这种算法适用于实时系统,其中...
- 进程的创建和销毁:模拟进程的生命周期,包括新建、就绪、执行、等待和结束状态。 - I/O操作:模拟进程在执行过程中可能遇到的I/O阻塞,此时CPU可以调度其他进程。 - 预占与非预占:对于抢占式调度,当高优先级...
在这个Java实现的课程设计中,我们将深入探讨操作系统进程调度的基本概念,并了解如何用Java语言来模拟这一过程。 首先,让我们了解什么是进程调度。在操作系统中,进程是执行中的程序实例,每个进程都有自己的内存...
在Java中,你可以创建一个队列数据结构来存储进程,并按照它们的到达时间顺序进行处理。 2. 短进程优先(SPF,Shortest Process First):此算法优先选择执行时间最短的进程,以减少平均等待时间。在Java中,可以...
以普通程序员身份认识高级语言VC++/Java/C#的进程创建与撤销工具。
在“java操作进程”的场景下,首先需要编写一个C++ DLL,该DLL包含了操作系统的进程管理功能,如创建、终止、查询进程等。这些功能通常对应于操作系统提供的API,例如Windows中的`CreateProcess`、`TerminateProcess...
这个类允许我们创建、控制以及与系统中的外部进程交互。例如,我们可以启动一个新的操作系统进程,传递参数,读取其输出,甚至控制其终止。 银行家算法是一种著名的避免死锁的策略,由艾兹格·迪杰斯特拉提出。在...
在 Java 中,可以创建一个队列数据结构(例如,`PriorityQueue` 或 `LinkedList`),将进程按它们到达的时间顺序存储,并依次处理。 2. 短进程优先(SPF)调度:SPF 算法优先选择预计运行时间最短的进程。为了实现 ...
图形界面通常使用Java Swing或JavaFX来创建,用于动态展示进程状态的变化,比如通过进度条或图表来表示每个进程的执行进度。 在实现过程中,需要注意以下几点: - **时间片管理**:对于轮转算法,需要一个定时器来...
在这个实验程序中,开发者利用JAVA 16的优势创建了一个用户友好的GUI,使得用户能够直观地观察和理解进程调度的过程。 图形化界面(GUI)是用户与程序交互的重要方式。在这个程序中,GUI可能包括进程列表、调度算法...
在阅读"守护进程(java).txt"这个文件时,你可以期待了解更多关于如何在Java中创建和管理守护线程的具体示例和最佳实践,包括如何处理线程间通信、异常处理以及如何优雅地关闭守护线程等。这些知识将帮助你深入理解...