您的位置:首页 > 编程语言 > Java开发

Java进程的创建

2015-08-29 22:09 573 查看
     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接口;

[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]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: