[Java][Android][Process] 分享 Process 运行命令行封装类型

简介:

我在以前的文章中提到,使用Java不会有一个问题,创建运行命令来创建太多进程后创建进程行语句。

[Android] ProcessBuilder与Runtime.getRuntime().exec分别创建进程的差别

进行多次測试后发现是由于没有正常退出进程,以及全然读取掉流数据。和关闭流导致的问题。

在多次优化后,建立例如以下封装类:

ProcessModel.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

/**
 * Create By Qiujuer
 * 2014-07-26
 * <p/>
 * 运行命令行语句静态方法封装
 */
public class ProcessModel {
    //换行符
    private static final String BREAK_LINE;
    //运行退出命令
    private static final byte[] COMMAND_EXIT;
    //错误缓冲
    private static byte[] BUFFER;

    /**
     * 静态变量初始化
     */
    static {
        BREAK_LINE = "\n";
        COMMAND_EXIT = "\nexit\n".getBytes();
        BUFFER = new byte[32];
    }


    /**
     * 运行命令
     *
     * @param params 命令參数
     *               <pre> eg: "/system/bin/ping", "-c", "4", "-s", "100","www.qiujuer.net"</pre>
     * @return 运行结果
     */
    public static String execute(String... params) {
        Process process = null;
        StringBuilder sbReader = null;

        BufferedReader bReader = null;
        InputStreamReader isReader = null;

        InputStream in = null;
        InputStream err = null;
        OutputStream out = null;

        try {
            process = new ProcessBuilder()
                    .command(params)
                    .start();
            out = process.getOutputStream();
            in = process.getInputStream();
            err = process.getErrorStream();

            out.write(COMMAND_EXIT);
            out.flush();

            process.waitFor();

            isReader = new InputStreamReader(in);
            bReader = new BufferedReader(isReader);

            String s;
            if ((s = bReader.readLine()) != null) {
                sbReader = new StringBuilder();
                sbReader.append(s);
                sbReader.append(BREAK_LINE);
                while ((s = bReader.readLine()) != null) {
                    sbReader.append(s);
                    sbReader.append(BREAK_LINE);
                }
            }

            while ((err.read(BUFFER)) > 0) {
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeAllStream(out, err, in, isReader, bReader);

            if (process != null) {
                processDestroy(process);
                process = null;
            }
        }

        if (sbReader == null)
            return null;
        else
            return sbReader.toString();
    }

    /**
     * 关闭全部流
     *
     * @param out      输出流
     * @param err      错误流
     * @param in       输入流
     * @param isReader 输入流封装
     * @param bReader  输入流封装
     */
    private static void closeAllStream(OutputStream out, InputStream err, InputStream in, InputStreamReader isReader, BufferedReader bReader) {
        if (out != null)
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        if (err != null)
            try {
                err.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        if (in != null)
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        if (isReader != null)
            try {
                isReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        if (bReader != null)
            try {
                bReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }


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

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

    /**
     * 销毁进程
     *
     * @param process 进程
     */
    private static void processDestroy(Process process) {
        if (process != null) {
            try {
                //推断是否正常退出
                if (process.exitValue() != 0) {
                    killProcess(process);
                }
            } catch (IllegalThreadStateException e) {
                killProcess(process);
            }
        }
    }
}

在进行批量压力測试到达125643线程的时候都不会发生此问题。与大家分享特此。

版权声明:本文博客原创文章,博客,未经同意,不得转载。





本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4750175.html,如需转载请自行联系原作者


相关文章
|
1月前
|
安全 Java 编译器
Java类型提升与类型转换详解
本文详解Java中的类型提升与类型转换机制,涵盖类型提升规则、自动类型转换(隐式转换)和强制类型转换(显式转换)的使用场景与注意事项。内容包括类型提升在表达式运算中的作用、自动转换的类型兼容性规则,以及强制转换可能引发的数据丢失和运行时错误。同时提供多个代码示例,帮助理解byte、short、char等类型在运算时的自动提升行为,以及浮点数和整型之间的转换技巧。最后总结了类型转换的最佳实践,如避免不必要的转换、使用显式转换提高可读性、金融计算中使用BigDecimal等,帮助开发者写出更安全、高效的Java代码。
111 0
|
28天前
|
安全 IDE Java
Java记录类型(Record):简化数据载体类
Java记录类型(Record):简化数据载体类
274 120
|
1月前
|
Java 测试技术
Java浮点类型详解:使用与区别
Java中的浮点类型主要包括float和double,它们在内存占用、精度范围和使用场景上有显著差异。float占用4字节,提供约6-7位有效数字;double占用8字节,提供约15-16位有效数字。float适合内存敏感或精度要求不高的场景,而double精度更高,是Java默认的浮点类型,推荐在大多数情况下使用。两者都存在精度限制,不能用于需要精确计算的金融领域。比较浮点数时应使用误差范围或BigDecimal类。科学计算和工程计算通常使用double,而金融计算应使用BigDecimal。
620 102
|
5月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
413 7
|
2月前
|
存储 Android开发 数据安全/隐私保护
Thanox安卓系统增加工具下载,管理、阻止、限制后台每个APP运行情况
Thanox是一款Android系统管理工具,专注于权限、后台启动及运行管理。支持应用冻结、系统优化、UI自定义和模块管理,基于Xposed框架开发,安全可靠且开源免费,兼容Android 6.0及以上版本。
153 4
|
5月前
|
缓存 Android开发 开发者
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
968 62
|
5月前
|
开发工具 Android开发 开发者
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
304 61
|
6月前
|
存储 传感器 缓存
java变量与数据类型:整型、浮点型与字符类型
### Java数据类型全景表简介 本文详细介绍了Java的基本数据类型和引用数据类型,涵盖每种类型的存储空间、默认值、取值范围及使用场景。特别强调了`byte`、`int`、`long`、`float`、`double`等基本类型在不同应用场景中的选择与优化,如文件流处理、金融计算等。引用数据类型部分则解析了`String`、数组、类对象、接口和枚举的内存分配机制。
182 15
|
7月前
|
缓存 Java 测试技术
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
788 3
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
|
5月前
|
Java
java中一个接口A,以及一个实现它的类B,一个A类型的引用对象作为一个方法的参数,这个参数的类型可以是B的类型吗?
本文探讨了面向对象编程中接口与实现类的关系,以及里氏替换原则(LSP)的应用。通过示例代码展示了如何利用多态性将实现类的对象传递给接口类型的参数,满足LSP的要求。LSP确保子类能无缝替换父类或接口,不改变程序行为。接口定义了行为规范,实现类遵循此规范,从而保证了多态性和代码的可维护性。总结来说,接口与实现类的关系天然符合LSP,体现了多态性的核心思想。
114 0