[Java][Android][Process] ProcessBuilder与Runtime区别

Android 同时被 2 个专栏收录
42 篇文章 0 订阅
13 篇文章 0 订阅

在Android中想要进行Ping,在不Root机器的情况下似乎还只能进行底层命调用才能实现。

因为在Java中要进行ICMP包发送需要Root权限。


于是只能通过创建进程来解决了,创建进程在Java中有两种方式,分别为:

1. 调用ProcessBuilder的构造函数后执行start()
2. 用Runtime.getRuntime().exec()方法执行


经过使用后发现两者有区别但是也并不是很大,两个例子说明:


1.调用ProcessBuilder的构造函数后执行start():

Process process = new ProcessBuilder("/system/bin/ping").redirectErrorStream(true).start();
OutputStream stdout = process.getOutputStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));


2.用Runtime.getRuntime().exec()方法执行:

Process process = Runtime.getRuntime().exec("/system/bin/ping");
OutputStream stdout = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedReader err= new BufferedReader(new InputStreamReader(stderr));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));

两者在执行效率上没啥区别,可能是我没有发现。两种测试的区别在于是否可以重定向错误流。

使用ProcessBuilder,可以通过redirectErrorStream(true)将错误输出流转移到标准输出流中,这样使用一次process.getInputStreamReader()就能读出该进程的所有输出。

而使用Runtime.getRuntime().exec()方法时,错误的输出流还需通过process.getErrorStream()来获得。


分享一个自己集合的一个进程执行后销毁的类:

import java.io.InputStream;
import java.io.OutputStream;

public class ProcessModel {

    /**
     * 通过Android底层实现进程关闭
     *
     * @param process
     */
    public static void killProcess(Process process) {
        int pid = getProcessId(process.toString());
        if (pid != 0) {
            try {
                android.os.Process.killProcess(pid);
            } catch (Exception e) {
                try {
                    process.destroy();
                } catch (Exception ex) {
                }
            }
        }
    }

    /**
     * 获取当前进程的ID
     *
     * @param str
     * @return
     */
    public static int getProcessId(String str) {
        try {
            int i = str.indexOf("=") + 1;
            int j = str.indexOf("]");
            String cStr = str.substring(i, j).trim();
            return Integer.parseInt(cStr);
        } catch (Exception e) {
            return 0;
        }
    }


    /**
     * 关闭进程的所有流
     *
     * @param process
     */
    public static void closeAllStream(Process process) {
        try {
            InputStream in = process.getInputStream();
            if (in != null)
                in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            InputStream in = process.getErrorStream();
            if (in != null)
                in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            OutputStream out = process.getOutputStream();
            if (out != null)
                out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 销毁一个进程
     *
     * @param process
     */
    public static void processDestroy(Process process) {
        if (process != null) {
            try {
                if (process.exitValue() != 0) {
                    closeAllStream(process);
                    killProcess(process);
                }
            } catch (IllegalThreadStateException e) {
                closeAllStream(process);
                killProcess(process);
            }
        }
    }


    /**
     * 通过线程进行异步销毁
     *
     * @param process
     */
    public static void asyncProcessDestroy(final Process process) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                processDestroy(process);
            }
        });
        thread.setDaemon(true);
        thread.start();
    }
}



奇怪的是,当使用线程进行大量的进程创建,最后达到一定数量(大约为1000个左右)的时候将会出现无法创建进程的情况;

此情况我不知怎么解决,自己想的是弄一个线程池里边放20个已经创建的进程,而外部的线程重复利用以及创建的进程,不知这样是否可行?

望大家探讨一下解决方法,谢谢了。

  • 3
    点赞
  • 8
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值