java多进程间(父进程与子进程)通信
一般我们在java中运行其它类中的方法时,无论是静态调用,还是动态调用,都是在当前的进程中执行的,也就是说,只有一个java虚拟机实例在运行。而有的时候,我们需要通过java代码启动多个java子进程。这样做虽然占用了一些系统资源,但会使程序更加稳定,因为新启动的程序是在不同的虚拟机进程中运行的,如果有一个进程发生异常,并不影响其它的子进程。
在Java中我们可以使用两种方法来实现这种要求。最简单的方法就是通过Runtime中的exec方法执行java classname。如果执行成功,这个方法返回一个Process对象,如果执行失败,将抛出一个IOException错误。下面让我们来看一个简单的例子。
// Test1.java文件
import java.io.*;
public class Test
{public static void main(String[] args){FileOutputStream fOut = new FileOutputStream("c:\\Test1.txt");fOut.close();System.out.println("被调用成功!");}
}
// Test_Exec.java
public class Test_Exec
{public static void main(String[] args){Runtime run = Runtime.getRuntime();Process p = run.exec("java test1"); }
}
通过java Test_Exec运行程序后,发现在C盘多了个Test1.txt文件,但在控制台中并未出现"被调用成功!"的输出信息。因此可以断定,Test已经被执行成功,但因为某种原因,Test的输出信息未在Test_Exec的控制台中输出。这个原因也很简单,因为使用exec建立的是Test_Exec的子进程,这个子进程并没有自己的控制台,因此,它并不会输出任何信息。
如果要输出子进程的输出信息,可以通过Process中的getInputStream得到子进程的输出流(在子进程中输出,在父进程中就是输入),然后将子进程中的输出流从父进程的控制台输出。具体的实现代码如下如示:
// Test_Exec_Out.java
import java.io.*;
public class Test_Exec_Out
{public static void main(String[] args){Runtime run = Runtime.getRuntime();Process p = run.exec("java test1"); BufferedInputStream in = new BufferedInputStream(p.getInputStream());BufferedReader br = new BufferedReader(new InputStreamReader(in));String s;while ((s = br.readLine()) != null)System.out.println(s); }
}
从上面的代码可以看出,在Test_Exec_Out.java中通过按行读取子进程的输出信息,然后在Test_Exec_Out中按每行进行输出。 上面讨论的是如何得到子进程的输出信息。那么,除了输出信息,还有输入信息。既然子进程没有自己的控制台,那么输入信息也得由父进程提供。我们可以通过Process的getOutputStream方法来为子进程提供输入信息(即由父进程向子进程输入信息,而不是由控制台输入信息)。我们可以看看如下的代码:
// Test2.java文件
import java.io.*;
public class Test
{public static void main(String[] args){BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.println("由父进程输入的信息:" + br.readLine());}
}
// Test_Exec_In.java
import java.io.*;
public class Test_Exec_In
{public static void main(String[] args){Runtime run = Runtime.getRuntime();Process p = run.exec("java test2"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));bw.write("向子进程输出信息");bw.flush();bw.close(); // 必须得关闭流,否则无法向子进程中输入信息// System.in.read();}
}
从以上代码可以看出,Test1得到由Test_Exec_In发过来的信息,并将其输出。当你不加bw.flash()和bw.close()时,信息将无法到达子进程,也就是说子进程进入阻塞状态,但由于父进程已经退出了,因此,子进程也跟着退出了。如果要证明这一点,可以在最后加上System.in.read(),然后通过任务管理器(在windows下)查看java进程,你会发现如果加上bw.flush()和bw.close(),只有一个java进程存在,如果去掉它们,就有两个java进程存在。这是因为,如果将信息传给Test2,在得到信息后,Test2就退出了。在这里有一点需要说明一下,exec的执行是异步的,并不会因为执行的某个程序阻塞而停止执行下面的代码。因此,可以在运行test2后,仍可以执行下面的代码。
exec方法经过了多次的重载。上面使用的只是它的一种重载。它还可以将命令和参数分开,如exec("java.test2")可以写成exec("java", "test2")。exec还可以通过指定的环境变量运行不同配置的java虚拟机。
除了使用Runtime的exec方法建立子进程外,还可以通过ProcessBuilder建立子进程。ProcessBuilder的使用方法如下:
// Test_Exec_Out.java
import java.io.*;
public class Test_Exec_Out
{public static void main(String[] args){ProcessBuilder pb = new ProcessBuilder("java", "test1");Process p = pb.start();… …}
}
在建立子进程上,ProcessBuilder和Runtime类似,不同的ProcessBuilder使用start()方法启动子进程,而Runtime使用exec方法启动子进程。得到Process后,它们的操作就完全一样的。
ProcessBuilder和Runtime一样,也可设置可执行文件的环境信息、工作目录等。下面的例子描述了如何使用ProcessBuilder设置这些信息。
ProcessBuilder pb = new ProcessBuilder("Command", "arg2", "arg2","");
// 设置环境变量
Map<String, String> env = pb.environment();
env.put("key1", "value1");
env.remove("key2");
env.put("key2", env.get("key1") + "_test");
pb.directory("..\abcd"); // 设置工作目录
Process p = pb.start(); // 建立子进程
若要更深入研究,请参考以下资源:
深入研究java.lang.ProcessBuilder类
深入研究java.lang.Process类
深入研究java.lang.Runtime类
相关文章:
java多进程间(父进程与子进程)通信
一般我们在java中运行其它类中的方法时,无论是静态调用,还是动态调用,都是在当前的进程中执行的,也就是说,只有一个java虚拟机实例在运行。而有的时候,我们需要通过java代码启动多个java子进程。这样做虽然…...
【从0到1设计一个网关】整合Nacos-服务注册与服务订阅的实现
文章目录 Nacos定义服务注册与订阅方法服务信息加载与配置实现将网关注册到注册中心实现服务的订阅 Nacos Nacos提供了许多强大的功能: 比如服务发现、健康检测。 Nacos支持基于DNS和基于RPC的服务发现。 同时Nacos提供对服务的实时的健康检查,阻止向不…...
【uniapp】短信验证码输入框
需求是短信验证码需要格子输入框 如图 网上找了一个案例改吧改吧 直接上代码 结构 <template><view class"verify-code"><!-- 输入框 --><input id"input" :value"code" class"input" :focus"isFocus"…...
负载均衡的综合部署练习(hproxy+keepalived和lvs-DR+keepalived+nginx+Tomcat)
一、haproxykeepalived haproxy 2台 20.0.0.21 20.0.0.22 nginx 2台 20.0.0.23 20.0.0.24 客户机 1台 20.0.0.30 这里没有haproxy不是集群的概念,他只是代理服务器。 访问他直接可以直接访问后端服务器 关闭防火墙 安装haproxy和环境: yum in…...
设计模式——策略模式(Strategy Pattern)+ Spring相关源码
文章目录 一、策略模式定义二、例子1. 菜鸟教程例子(略有改动)1.1 、定义。1.2、定义加法策略类1.3、定义乘法策略类1.4、创建 Context 类1.5、使用 2、JDK awt包——BufferStrategy3、Spring源码 —— InstantiatorStrategy4、Spring源码 —— Instanti…...
ORB-SLAM3算法2之开源数据集运行ORB-SLAM3生成轨迹并用evo工具评估轨迹
文章目录 0 引言1 数据和真值1.1 TUM1.2 EuRoc1.3 KITTI2 ORB-SLAM3的EuRoc示例3 ORB-SLAM3的TUM-VI示例4 ORB-SLAM3的ROS各版本示例4.1 单目4.2 单目和IMU4.3 双目4.4 双目和IMU4.5 RGB-D0 引言 ORB-SLAM3算法1 已成功编译安装ORB-SLAM3到本地,本篇目的是用TUM、EuRoc和KITT…...
Qt 序列化函数和反序列化函数
文章目录 界面学生类序列化函数反序列化函数刷新所选择的下拉表值添加 界面 学生类 // 创建学生信息类 class studentInfo { public:QString id; // 学号QString name; // 学生姓名QString age; // 学生年龄// 重写QDataStream& operator<<操作符&…...
Linux之线程池
线程池 线程池概念线程池的应用场景线程池实现原理单例模式下线程池实现STL、智能指针和线程安全其他常见的各种锁 线程池概念 线程池:一种线程使用模式。 线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待…...
MAC安装stable diffusion
./webui.sh --precision full --no-half-vae --disable-nan-check --api Command: "/Users/xxxx/aigc/stable-diffusion-webui/venv/bin/python3" -m pip install torch2.0.1 torchvision0.15.2 Error code: 2 执行命令: pip install torch2.0.1 torchvi…...
FPGA_状态机工作原理
FPGA_状态机介绍和工作原理 状态机工作原理Mealy 状态机模型Moore 状态机模型状态机描述方式代码格式 总结 状态机工作原理 状态机全称是有限状态机(Finite State Machine、FSM),是表示有限个状态以及在这些状态之间的转移和动作等行为的数学…...
【python练习】python斐波那契数列超时问题
计算斐波那契数列第n项的数字 Description计算斐波那契数列第n项的数字,其中f(1)f(2)1,f(n)f(n-1)f(n-2),如1,1,2,3,5,......Input 正整数n(n<100)Output 一个整数f(n)Sample Input 1 8 Sample Output 1…...
SpringCloud 微服务全栈体系(五)
第七章 Feign 远程调用 先来看我们以前利用 RestTemplate 发起远程调用的代码: 存在下面的问题: 代码可读性差,编程体验不统一 参数复杂 URL 难以维护 Feign 是一个声明式的 http 客户端,官方地址:https://github.…...
msvcp140.dll丢失的正确解决方法
在使用电脑中我们经常会遇到一些错误提示,其中之一就是“msvcp140.dll丢失”。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题,我们需要采取一些措施来修复丢失的msvcp140.dll文件。本文将介绍6个不同的解决方法,帮助读者解决…...
go pprof 如何使用 --chatGPT
gpt: pprof 是 Go 语言的性能分析工具,它可以用来检测 CPU 使用情况、内存使用情况、以及阻塞情况。你可以使用 pprof 来帮助诊断程序的性能问题,包括内存泄漏。 以下是如何使用 pprof 来分析内存泄漏的基本步骤: 1. **导入 pprof 包**&am…...
大数据可视化BI分析工具Apache Superset实现公网远程访问
大数据可视化BI分析工具Apache Superset实现公网远程访问 文章目录 大数据可视化BI分析工具Apache Superset实现公网远程访问前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网…...
软考系统架构师知识点集锦二:软件工程
一、考情分析 二、考点精讲 2.1 软件过程模型 (1)原型模型 典型的原型开发方法模型。适用于需求不明确的场景,可以帮助用户明确需求。可以分为[抛弃型原型]与[演化型原型] 原型模型两个阶段: 1、原型开发阶段;2、目标软件开发阶段。 &#x…...
Go并发:使用sync.Pool来性能优化
简介 在Go提供如何实现对象的缓存池功能?常用一种实现方式是:sync.Pool, 其旨在缓存已分配但未使用的项目以供以后重用,从而减轻垃圾收集器(GC)的压力。 快速使用 sync.Pool的结构也比较简单,常用的方法…...
git stash的使用方法
git stash的使用方法 应用场景 当我们在开发一个新功能的时候,或者开发到一半,然后就收到了线上master 出现了bug,当分支开发已经进行了或者进行到一半了,这时怎么办呢? 这时解决方案有两种:一种是先先将当…...
【影刀演示_发送邮件的格式化HTML留存】
发送邮件的格式化HTML留存 纯文本: 亲爱的小张: 端午节将至,公司为了感谢大家一年以来的辛勤工作和付出,特别为大家准备了京客隆超市福利卡,希望为大家带来些许便利和节日的喜悦。 以下是您的福利卡卡号和密码,请您…...
深度学习(4)---生成式对抗网络(GAN)
文章目录 一、原理讲述1.1 概念讲解1.2 生成模型和判别模型 二、训练过程2.1 训练原理2.2 损失函数 三、应用 一、原理讲述 1.1 概念讲解 1. 生成式对抗网络(Generative Adversarial Network,GAN)是一种深度学习模型,是近年来复杂…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
