Java - 多进程编程(对比线程、API 操作)

news2024/12/27 12:46:02

目录

一、多进程编程

1.1、为什么要使用多进程编程

1.2、Java 中多进程编程的实现

1.2.1、前言

1.2.2、进程创建

1.2.3、进程等待

1.2.4、封装操作到一个工具类中


一、多进程编程


1.1、为什么要使用多进程编程

一个 .exe 文件执行以后,就会变成一个进程. 

多进程的由来:为了解决某些大型复杂问题,就需要把一个很大的任务,拆分成一个小的任务,进一步的,就需要使用 “多进程编程”,也就是床技安多个进程,每个进程分别负责其中一部分任务.  与此同时,也带来一个问题——“进程的 创建/销毁,比较重量(低效)”.

线程的由来:引入了线程,相比于 进程的 创建/销毁 更加高效,因此 Java 圈子中,大部分并发编程都是通过多线程的方式来实现.

什么情况下要使用多进程编程呢?

进程相比于线程最大的优势就是:进程的 “独立性”.

  • 多线程劣势:一个操作系统上,同一时刻一个进程中运行着多个线程(共用一个地址空间),某个线程挂了,就可能把整个线程带走;
  • 多进程优势:一个操作系统上,同一时刻运行着很多进程,由于不同的进程有各自的地址空间,那么即使某一个进程挂了,也不会影响到其他进程.

比如在一个 OJ 系统中,用户提交的代码就是一个独立的逻辑,整个逻辑就需要使用多进程的方式来执行.  因为用户的代码很有可能是存在问题的(一运行就崩溃),使用多线程就很有可能导致用户代码直接把整个服务器进程搞挂.

1.2、Java 中多进程编程的实现

1.2.1、前言

在操作系统的角度上(例如 Linux),提供了很多和多线程编程相关的接口,例如 进程创建、进程终止、进程等待、进程程序替换、进程间通讯.

但是在 Java 中对这些操作进行了限制,最终只提供了两个操作:进程创建 和 进程等待.

1.2.2、进程创建

通过 Runtime 实例中的 exec 方法(参数是一个字符串,相当于在 cmd 中输入了一个对应的指令)就可以创建出一个进程, 被创建出来的进程称为 “子进程”,创建子进程的进程称为 “父进程”.  咱们的服务器进程就相当于父进程,它可以有多个子进程,但是一个子进程只能有一个父进程.

一个进程在启动的时候,就会自动以下打开三个文件:

  1. 标准输入:对应到键盘.
  2. 标准输出:对应到显示器,用来正确的输出.
  3. 标准错误:对应到显示器,用来展示错误输出.

Ps:在 IDEA 中式看不到子进程的输出的,想要获取,可以手动获取.

例如,创建一个子进程运行 javac 命令,通过输入输出流,将子进程的 标准输出 和 错误输出 写到对应文件中. 

    public static void main(String[] args) throws IOException, InterruptedException {
        //Runtime 再 JVM 中是一个单例
        Runtime runtime = Runtime.getRuntime();
        //Process 就表示进程
        Process process = runtime.exec("javac");

        //获取子进程的标准输出和标准错误,并写道两个文件中
        //1.标准hou出
        //1) 通过 标准输入流 将子进程的标准输出读出来,写入到 stdout.txt 文件中
        InputStream stdoutFrom = process.getInputStream();
        FileOutputStream stdoutTo = new FileOutputStream("stdout.txt");
        while(true) {
            int ch = stdoutFrom.read();
            if(ch == -1) { //读到 EOF 为止(EOF 就是 -1)
                break;
            }
            stdoutTo.write(ch);
        }
        //2) 释放文件描述符
        stdoutFrom.close();
        stdoutTo.close();

        //2.标准错误
        //2) 通过标准输入流 将子进程的标准错误读出来,写入到 stderr.txt
        InputStream stderrFrom = process.getErrorStream();
        FileOutputStream stderrTo = new FileOutputStream("stderr.txt");
        while(true) {
            int ch = stderrFrom.read();
            if(ch == -1) {
                break;
            }
            stderrTo.write(ch);
        }
        //2) 释放文件描述符
        stderrFrom.close();
        stderrTo.close();

    }

运行后可以看到生成如下两个文件:

由于这里我只是单纯的输入 javac 命令(没有指定编译的 jar 包),因此是一个错误命令,那么就可以在 标准错误 中看到如下信息:

Ps:javac 往控制台输出的命令,再 windows 简体中文版系统中,默认是 gbk 编码,idea 默认式 utf8,打开后可能会乱码,因此只需要再 idea 提示中,通过 gbk 重新加载即可.

在 cmd 中输入 javac 也是一样的结果:

1.2.3、进程等待

在某些场景中,我们希望父进程等待子进程执行完毕以后,再执行后续的代码. 

例如,OJ 系统就需要让用户提交代码,然后编译执行代码,再把执行结果的响应返回给用户.

具体实现如下:

通过 Process 类中的 waitFor 方法实现进程等待,父进程执行到 waitFor 的时候就会阻塞,知道子进程执行完毕为止(类似 Thread.join). 最后会返回一个退出码,表示子进程执行结果是否 ok,正常退出就返回 0,异常退出(子进程执行过程中抛异常了)就非0.

        //进程等待
        int exitCode = process.waitFor();
        System.out.println(exitCode);

1.2.4、封装操作到一个工具类中

通常,我们会将进程创建和等待封装到一个工具类中去使用.

public class CommandUtil {

    /**
     * @param cmd 进程要执行的命令
     * @param stdout 标准输出文件名 + 后缀
     * @param stderr 标准错误文件名 + 后缀
     * @return 进程等待后返回的状态码
     */
    public static int run(String cmd, String stdout, String stderr) {
        try {
            //1.获取 Runtime 实例,执行 exec 方法
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec(cmd);
            //2.获取 标准输出
            if(stdout != null) {
                InputStream stdoutFrom = process.getInputStream();
                FileOutputStream stdoutTo = new FileOutputStream(stdout);
                while(true) {
                    int read = stdoutFrom.read();
                    if(read == -1) {
                        break;
                    }
                    stdoutTo.write(read);
                }
                stdoutFrom.close();
                stdoutTo.close();
            }
            //3.获取 标准错误
            if(stderr != null) {
                InputStream stderrFrom = process.getErrorStream();
                FileOutputStream stderrTo = new FileOutputStream(stderr);
                while(true) {
                    int read = stderrFrom.read();
                    if(read == -1) {
                        break;
                    }
                    stderrTo.write(read);
                }
                stderrFrom.close();
                stderrTo.close();
            }
            //4.进程等待
            return process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回异常的状态码
        return 1;
    }

    //测试
    public static void main(String[] args) {
        int result = run("javac", "stdout.txt", "stderr.txt");
        System.out.println(result);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1117793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高质量发展新引擎:智能工业操作系统助力产业升级

工业操作系统是推动制造业高质量发展的重要支撑,也是推动经济发展方式转变的重要手段。打造自主可控的工业实时操作系统是实现工业科技自立自强的必然要求,是推动高质量发展的必由之路。 基于软件定义控制的智能工业操作系统 Intewell操作系统是由科东…

【技术番外篇】国家高新技术企业 认定

第一个网站:高新技术企业认定管理工作网 http://www.innocom.gov.cn/gqrdw/index.shtml 多给认定机构打咨询电话,少走弯路 有什么不懂的地方就可以打电话咨询专业人士 http://www.innocom.gov.cn/gqrdw/c101321/201905/3b94fbc91a894bcbba97fb7125c9…

【ChatGLM2-6B】nginx转发配置

背景 好不容易把ChatGLM2-6B大语言模型部署好了,使用streamlit方式启动起来了,终于可以愉快的玩耍了,然后想着申请一个域名,使用HTTPS协议访问,但实践过程中,发现这个大语言模型的nginx转发配置还是有点小…

Swingbench 压力测试(超详细)

目录 前提需要有配置好的oracle哦 1、环境准备 2、安装Swingbench 3、造数据 4、压测 前提需要有配置好的oracle哦 1、环境准备 启动监听 lsnrctl start 启动数据库 sqlplus / as sysdba startup 创建表 CREATE TABLESPACE soe DATAFILE /u01/app/oracle/oradata/or…

重生奇迹MU游戏上格斗家挂机小技巧

重生奇迹MU作为一个独特的职业,重生奇迹MU游戏中的格斗家有着多种挂机技巧,以下是一些重生奇迹MU格斗家挂机小技巧供玩家参考: 1.使用幽冥光速拳 幽冥光速拳是格斗家的核心技能之一,可以快速消灭怪物并提高经验值。建议玩家将此…

【PX4报错】Crash dumps present on SD,vehicle needs service

报错: Critical: Preflight Fail: Crash dumps present on SD,vehicle needs service 解决: 将COM_ARM_HFLT_CHECK改为Disabled 参考: PX4常见解锁失败报错及解决方法

PCA降维可视化

二维 import pandas as pd import warnings warnings.filterwarnings("ignore")df pd.read_csv(data/data.csv).dropna() features df.columns[:-1] X, y df[features], df[label]from sklearn.preprocessing import MinMaxScaler # 创建MinMaxScaler对象 scaler…

论坛介绍|COSCon'23 大数据(D)

众多开源爱好者翘首期盼的开源盛会:第八届中国开源年会(COSCon23)将于 10月28-29日在四川成都市高新区菁蓉汇举办。本次大会的主题是:“开源:川流不息、山海相映”!各位新老朋友们,欢迎到成都&a…

柯桥银泰附近有学德语的地方吗,留学德语培训

01 die Garantiefr jemandem/etwas 给某人或某事的保障 Das System bietet die Garantie fr die Bauer. 02 der Gebrauch von etwas 使用某物 Wir haben den Gebrauch vom Computer gelerbt. 我们学会了使用电脑。 03 Die Geduld mit jemandem/etwas 对..的耐心 Der Lehre…

llava1.5-部署

llava1.5 ——demo部署 下载代码和权重 新建weights文件夹,并下载到LLaVA/weights/中。->需要修改文件名为llava-版本,例如llava-v1.5-7b. 运行 启动控制台 python -m llava.serve.controller --host 0.0.0.0 --port 4006启动gradio python -m…

网络拥塞控制的经济学原理

作为一个流通和兑换系统(与被发送速率兑换出的带宽不同,公路交通不是兑换系统,车辆只是单体),网络传输与货币流通和兑换是一回事,借一些经济学术语能更深刻理解拥塞的成因和缓解以及制定拥塞控制策略,这是一个新视角。…

2024年浙大MPA复试可能面临的变数:权重加大

熟悉浙大mpa项目常规批复试规则的同学都知道,每年的复试成绩权重一般都在40%,这个权重对于每年复试后综合成绩的排名影响会比较大,按照mpa联考复试1分等于初试3分的规则,联考笔试成绩假如有15分差异的两个考生,复试成绩…

Docker 部署本地爬虫项目到服务器

笔记:一直想写一篇博客的,那就趁着周末闲暇时光记录一下。 目录 一、前提准备 二、Docker部署爬虫示例 整体梳理 1、打包构建本地项目镜像 2、在 hub 网站上 创建一个仓库。 3、将本地镜像与hub上的仓库打上标签 4、确保已登录 Dockerhub 账号 …

一键掌握多家快递信息,快递批量查询高手软件助你高效管理物流

一键掌握多家快递信息,快递批量查询高手软件助你高效管理物流 在当今这个高度信息化的时代,快递行业的发展可谓日新月异。随着网购的普及,如何高效、准确地掌握多家快递公司的信息,成为了很多消费者和管理者面临的难题。为了解决…

fastadmin笔记,fastadmin表格功能

fastadmin笔记 官方文档请到: https://ask.fastadmin.net/article/323.html自行查阅 1、默认有个切换功能。 浏览模式可以切换卡片视图和表格视图两种模式,如果不需要此功能 在该控制器对应的js 文件中添加上showToggle:false即可。 2、导出功能 …

谷歌浏览器误代码STATUS_INVALID_IMAGE_HASH如何一行代码解决

一、直入主题: 1.谷歌浏览器突然就不能用了,如下图: 2.如何解决 --test-type -no-sandbox 卸载浏览器重装还是一样的问题,目前我们的谷歌浏览器版本号:Chrome 已是最新版本 版本 118.0.5993.89(正式版本&a…

2023年中职组“网络安全”赛项 云南省竞赛任务书

2023年中职组“网络安全”赛项 云南省竞赛任务书 一、竞赛时间 总计:360分钟 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A模块 A-1 登录安全加固 180分钟 200分 A-2 本地安全策略配置 A-3 流量完整性保护 A-4 事件监控 A-5 服务加固 A-6 防火墙策…

同步网盘选择指南:哪个同步网盘更好用?

同步盘是当下热门的云存储服务之一,它可以将您的文件在不同设备之间进行同步,使您可以随时随地访问和共享您的文件,因此受到了许多用户的喜爱。 一、什么是同步盘 首先到底什么是同步盘?同步盘是指一种云存储服务,它…

回归预测 | MATLAB实现BO-GRU贝叶斯优化门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现BO-GRU贝叶斯优化门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现BO-GRU贝叶斯优化门控循环单元多输入单输出回归预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-GRU贝叶斯优化门控循环单元回归预测。基于贝…

开关电源负载调整率测试规范国标有哪些?负载调整率测试方法是什么?

负载调整率是用来描述在额定电压下负载电流从0变化到最大时,输出电压相应的变化情况。它是衡量电源芯片好坏的重要指标,因此负载调整率测试是必不可少的环节。那么要如何测试电源芯片负载调整率呢?有哪些测试规范呢? 开关电源芯片测试规范 适用范围&am…