码迷,mamicode.com
首页 > 编程语言 > 详细

Java进程的创建

时间:2015-08-29 23:23:47      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:

     Java线程创建有两种形式,一种是继承Thread,一种是实现Runnable接口。
    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接口;

而Java中进程该如何创建呢,有两种实现方法:一种是使用ProcessBuilder.start来创建;一种是使用Runntime.exec实现;

一、使用ProcessBuilder.start创建
1、使用:
       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形式,一种是不定长参数形式;

4、ProcessBuilder是通过start方法来启动Process:
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的一系列处理,最终通过
     ProcessImpl.start(cmdarray,environment,dir,redirects,redirectErrorStream);
来启动进程。

5、来看看ProcessImpl(和Android中Context,ContextImpl略像)
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的具体实现类。

二、使用Runtime.exec来创建
1、使用
    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() {}
}
很明显的单例模式。

3、Runtime#exec:
    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组装成一个字符串的方法。


版权声明:本文为博主原创文章,未经博主允许不得转载。

Java进程的创建

标签:

原文地址:http://blog.csdn.net/woliuyunyicai/article/details/48092457

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!