Java——进程
来源:互联网 发布:pg报丧女妖网络限定 编辑:程序博客网 时间:2024/06/08 11:52
进程
进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位, 每个进程都有其自己的内存空间。Java中创建进程其实是创建了操作系统的一个进程,Java虚拟机本身就是一个进程,该进程创建了多个线程能够同时运行的条件。
进程特征
动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的;
并发性:任何进程都可以同其他进程一起并发执行;
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。
结构特征:进程由程序、数据和进程控制块三部分组成。
进程间通信
大多数操作系统都支持进程间通信( Inter Process Communication,简称 IPC)资源,如管道,共享内存和套接字等。(这块还不是很清楚)
Java进程的创建
Java提供了两种方法用来创建进程。
使用Runtime的exec()方法
源码中exec()方法最后是调用了ProcessBuilder的start()方法创建进程,源码如下。
public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException { return new ProcessBuilder(cmdarray) .environment(envp) .directory(dir) .start(); }
我用的是mac,看到的调用链是
Runtime的exec()——》new ProcessBuilder调用start()方法——》ProcessImpl.start()——》new UNIXProcess
UNIXProcess继承自抽象类Process,是实现了Process中方法的final类,该类中有处理进程的一些native方法。
Java.lang.Runtime.exec 方法和 Java.lang.ProcessBuilder.start 方法都可以创建一个本地的进程,然后返回代表这个进程的 Java.lang.Process 引用。
参考jdk1.8的源码
示例代码
在某个目录执行ls命令,列出目录下内容。
public int createProcessByRunTime() throws IOException{ int resultCode = -1; Process process = Runtime.getRuntime().exec("top", null, new File("/Users/gary/Documents/workspace")); //获取进程执行后结果 try(InputStream inputStream = process.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){ byte[] buf = new byte[1024]; int length; while((length = inputStream.read(buf)) != -1){ outputStream.write(buf, 0, length); } String result = outputStream.toString("utf-8"); System.out.println(result); //阻塞当前线程直到进程执行结束,执行成功返回0 resultCode = process.waitFor(); //立即返回执行结果,进程没有结束,可能会抛异常 IllegalThreadStateException //resultCode = process.exitValue(); return resultCode; } catch(InterruptedException e) { e.printStackTrace(); } return resultCode; }
运行结果:
RemoteSystemsTempFilesServerscommongradlePracticestatistics0
比如把程序的 ls
命令换成 top
命令,然后用 process.exitValue()
获取返回值,就会报下面的错误。
Exception in thread "main" java.lang.IllegalThreadStateException: process hasn't exited
使用ProcessBuilder的start()方法
看源码可以发现start方法中是调用了ProcessImpl类的start()方法,可以预先配置 ProcessBuilder 的属性是通过 ProcessBuilder 创建进程的最大优点。
示例代码
public int createProcessByProcessbuilder() throws IOException{ int resultCode = -1; ProcessBuilder processBuilder = new ProcessBuilder("ls"); //默认为FALSE,设为true后,标准错误将与标准输出合并,通过getInputStream获取输出信息 processBuilder.redirectErrorStream(true); Process process = processBuilder.directory(new File("/Users/gary/Documents/workspace")).start(); //获取进程执行后结果 try(InputStream inputStream = process.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){ byte[] buf = new byte[1024]; int length; while((length = inputStream.read(buf)) != -1){ outputStream.write(buf, 0, length); } String result = outputStream.toString("utf-8"); System.out.println(result); //阻塞当前线程直到进程执行结束 resultCode = process.waitFor(); //立即返回执行结果,进程没有结束,可能会抛异常 IllegalThreadStateException //resultCode = process.exitValue(); return resultCode; }catch(InterruptedException e) { e.printStackTrace(); } return resultCode; }
获取进程执行后返回码
一个程序/进程在执行结束后会向操作系统返回一个整数值,0一般代表执行成功,非0表示执行出现问题。有两种方式可以用来获取进程的返回值:一是利用waitFor(),该方法是阻塞的,直到进程执行完成后再返回。该方法返回一个代表进程返回值的整数值;另一个方法是调用exitValue()方法,该方法是非阻塞的,调用立即返回。但是如果进程没有执行完成,则抛出异常IllegalThreadStateException
。
可以使用ProcessBuilder的redirectErrorStream(true)方法将标准错误与标准输出合并,这时候只要读取标准输出的数据就可以了。
参考资料
java创建进程(很详细)
Java 中的进程与线程
- Java——进程
- Java——创建进程
- java必备——进程?线程?
- java回忆录——进程和线程
- Java——进程和线程
- java基础——进程和线程
- Java基础—多线程和多进程
- 进程—僵尸进程与孤儿进程
- 进程—僵尸进程与孤儿进程
- 进程—进程调度(1)
- 进程篇—进程整理
- JAVA学习笔记49——线程概念+进程、线程区别+创建进程三种方法
- JAVA学习笔记50——线程状态+停止进程+阻塞进程
- 黑马程序员——java小结_010_进程和线程
- Java并发1——进程和线程
- 黑马程序员——JAVA基础------进程和线程
- <JAVA学习笔记4>——进程、线程简单介绍
- java学习记录(15)——线程与进程
- jquery 书写全选反选功能
- 回溯算法概括
- OpenGL画点
- 几种常见较经典的显著性检测算法
- Unix环境高级编程第三版中apue.h头文件如何配置
- Java——进程
- 【量化入门】通过几种常见的量化策略框架,学习量化炒股
- [BZOJ1415][Noi2005]聪聪和可可(bfs+概率期望+记搜)
- STM32数据类型
- Spark Scala DataFram join 操作
- Shell编程之控制结构if
- 【Web】理解jquery的$.extend()、$.fn和$.fn.extend()
- Linux+php+apache+oracle环境搭建之CentOS下源码编译安装PHP
- swift 类似微信朋友圈聊天界面