Java进程的创建
2015-08-29 22:09
573 查看
Java线程创建有两种形式,一种是继承Thread,一种是实现Runnable接口。
可以看到Thread其实本质上实现了Runnable接口;
[align=left]
[/align]
[align=left]而Java中进程该如何创建呢,有两种实现方法:一种是使用ProcessBuilder.start来创建;一种是使用Runntime.exec实现;[/align]
[align=left]
[/align]
[align=left]一、使用ProcessBuilder.start创建[/align]
[align=left]1、使用:[/align]
2、先来看进程Process的主体源码:
3、ProcessBuilder的构造函数:
[align=left]
[/align]
[align=left]4、ProcessBuilder是通过start方法来启动Process:[/align]
[align=left]
[align=left]来启动进程。[/align]
[align=left]
[/align]
[align=left]5、来看看ProcessImpl(和Android中Context,ContextImpl略像)[/align]
[align=left]
[/align]
[align=left]二、使用Runtime.exec来创建[/align]
[align=left]1、使用[/align]
2、Runtime类:
[align=left]
[/align]
[align=left]3、Runtime#exec:[/align]
[align=left]
[/align]
private class NewThread extends Thread { @Override public void run(){ // do Something } } private class NewRunnable implements Runnable { @Override public void run(){ // do Something } }代码中使用:
new NewThread().start(); new Thread( new NewRunnable()).start();其实两者本质上是相同的,Thread、Runnable源码如下:
class Thread implements Runnable public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run </code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run();
可以看到Thread其实本质上实现了Runnable接口;
[align=left]
[/align]
[align=left]而Java中进程该如何创建呢,有两种实现方法:一种是使用ProcessBuilder.start来创建;一种是使用Runntime.exec实现;[/align]
[align=left]
[/align]
[align=left]一、使用ProcessBuilder.start创建[/align]
[align=left]1、使用:[/align]
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ipconfig/all"); Process process = null; try { process = pb.start(); } catch (IOException e) { e.printStackTrace(); } System.out.println(process.isAlive()); Scanner scanner = new Scanner (process.getInputStream()); while (scanner.hasNextLine()) { System.out.println(scanner.nextLine()); } scanner.close();
2、先来看进程Process的主体源码:
public abstract class Process { abstract public OutputStream getOutputStream(); //获取进程的输出流 abstract public InputStream getInputStream(); //获取进程的输入流 abstract public InputStream getErrorStream(); //获取进程的错误流 abstract public int waitFor() throws InterruptedException; //让进程等待 abstract public int exitValue(); //获取进程的退出标志 abstract public void destroy(); //摧毁进程 public Process destroyForcibly() { destroy(); return this ; } public boolean isAlive() { try { exitValue(); return false ; } catch(IllegalThreadStateException e) { return true ; } } }
3、ProcessBuilder的构造函数:
public final class ProcessBuilder{ private List<String> command; private File directory ; private Map<String,String> environment; private boolean redirectErrorStream ; private Redirect[] redirects ; public ProcessBuilder( List<String > command) { if (command == null) throw new NullPointerException(); this.command = command; } public ProcessBuilder( String... command) { this.command = new ArrayList <>(command.length ); for (String arg : command) this.command .add(arg); } }支持两种构造函数,一种是List形式,一种是不定长参数形式;
[align=left]
[/align]
[align=left]4、ProcessBuilder是通过start方法来启动Process:[/align]
public Process start() throws IOException { // Must convert to array first -- a malicious user-supplied // list might try to circumvent the security check. String[] cmdarray = command.toArray(new String[command .size()]); cmdarray = cmdarray.clone(); for (String arg : cmdarray) if (arg == null ) throw new NullPointerException(); // Throws IndexOutOfBoundsException if command is empty String prog = cmdarray[0]; SecurityManager security = System.getSecurityManager(); if (security != null) security.checkExec(prog); String dir = directory == null ? null : directory.toString(); for ( int i = 1; i < cmdarray.length; i++) { if (cmdarray[i].indexOf('\u0000' ) >= 0) { throw new IOException( "invalid null character in command" ); } } try { return ProcessImpl.start(cmdarray, environment, dir, redirects, redirectErrorStream); } catch (IOException | IllegalArgumentException e) { ...... } }前面是对commands的一系列处理,最终通过
[align=left]
ProcessImpl.start(cmdarray,environment,dir,redirects,redirectErrorStream);[/align]
[align=left]来启动进程。[/align]
[align=left]
[/align]
[align=left]5、来看看ProcessImpl(和Android中Context,ContextImpl略像)[/align]
final class ProcessImpl extends Process { static Process start(String cmdarray[], java.util.Map<String,String> environment, String dir, ProcessBuilder.Redirect[] redirects, boolean redirectErrorStream)throws IOException{ String envblock = ProcessEnvironment.toEnvironmentBlock(environment); try { ....... return new ProcessImpl(cmdarray, envblock, dir, stdHandles, redirectErrorStream); } finally { ....... } } }可以看到最终返回的Process的实际类型是ProcessImpl对象;ProcessImpl是抽象类Process的具体实现类。
[align=left]
[/align]
[align=left]二、使用Runtime.exec来创建[/align]
[align=left]1、使用[/align]
String cmd = "cmd "+ "/c " +"ipconfig/all" ; Process process = Runtime.getRuntime().exec(cmd); Scanner scanner = new Scanner (process.getInputStream()); while(scanner.hasNextLine()){ System.out.println(scanner.nextLine()); } scanner.close();
2、Runtime类:
public class Runtime { private static Runtime currentRuntime = new Runtime(); public static Runtime getRuntime() { return currentRuntime ; } private Runtime() {} }很明显的单例模式。
[align=left]
[/align]
[align=left]3、Runtime#exec:[/align]
public Process exec(String command) throws IOException { return exec(command, null , null ); } public Process exec(String command, String[] envp, File dir) throws IOException { if (command.length() == 0) throw new IllegalArgumentException( "Empty command"); StringTokenizer st = new StringTokenizer (command); String[] cmdarray = new String[st.countTokens()]; for (int i = 0; st.hasMoreTokens(); i++) cmdarray[i] = st.nextToken(); return exec(cmdarray, envp, dir); } public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException { return new ProcessBuilder (cmdarray) . environment(envp) .directory(dir) .start(); }可以看到最终依然是调用ProcessBuilder.start来创建的,两者原理实质相同;只是由于构造函数的不同,Runtime.exec方法只支持将所有commands组装成一个字符串的方法。
[align=left]
[/align]
相关文章推荐
- Java关键字final、static使用总结
- Java集合概述Set、List、Map
- 黑马程序员--Java_JDK新特性
- JAVA中常见容器类总结
- 【Java】Hello World
- Spring MVC Velocity模板引擎
- java注解(Annotation)解析
- 总结一下今天回顾的JavaIO的一些基本内容
- java下载文件代码
- JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
- eclipse在资源管理器中打开文件
- 初识JAVA5(线程)
- Spring框架简介和初次框架配置
- Spring笔记——Spring框架简介和初次框架配置
- 初识JAVA4(抽象类、接口、多态)
- java按指定编码写入和读取文件内容的类
- Struts1.x 总结(很全面)
- 初识JAVA3(重载、单子模式)
- Java中的异常(2)
- 用Eclipse 开发Dynamic Web Project应用程序 【转】