Java线程创建有两种形式,一种是继承Thread,一种是实现Runnable接口。
2、先来看进程Process的主体源码:
3、ProcessBuilder的构造函数:
2、Runtime类:
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组装成一个字符串的方法。