【JAVA基础面经】进程间的通信方式

张开发
2026/4/13 19:39:28 15 分钟阅读

分享文章

【JAVA基础面经】进程间的通信方式
文章目录前言1.管道Pipe2.命名管道FIFO3.消息队列4.共享内存5.信号量6.信号Signal7.Socket面试问题前言进程是系统资源分配的最小单位每个进程拥有独立的地址空间。为了保证不同进程之间能够交换数据、同步状态、协同工作操作系统提供了多种 IPC 机制。1.管道Pipe内核中开辟一个固定大小的缓冲区一个进程写入另一个进程读取。半双工数据单向流动只能在父子进程或兄弟进程间使用因为有共同祖先读取时如果没有数据会阻塞直到有数据或所有写端关闭Java 中的体现ProcessBuilder 启动子进程后可以通过 Process.getInputStream() / getOutputStream() 获得管道流实现父进程与子进程通信。// 父进程与子进程通过管道通信示例ProcessBuilderpbnewProcessBuilder(grep,java);Processppb.start();// 向子进程的标准输入写入数据try(OutputStreamosp.getOutputStream()){os.write(java is fun\npython is fun.getBytes());}// 读取子进程的标准输出try(BufferedReaderreadernewBufferedReader(newInputStreamReader(p.getInputStream()))){reader.lines().forEach(System.out::println);}2.命名管道FIFO与普通管道的区别在文件系统中有一个路径名不相关的进程可以通过该文件名进行通信。特点遵循先进先出原则写入的数据被另一进程读取后即从内核缓冲区移除。使用场景需要长期存在的、无亲缘关系的进程间的数据流。Java 标准库没有直接封装 FIFO但可以通过 JNA 或直接操作 /tmp/myfifo 等文件路径使用 RandomAccessFile 以读写方式打开Linux 下需要配合 mkfifo 预先创建3.消息队列即消息的链表存储在内核中每个消息有类型和正文。优点解耦发送方和接收方不需要同时运行支持多条消息有优先级数据有边界不像流式管道需要自己解析缺点消息大小通常有限制内核空间拷贝数据有一定开销。可以使用 Kafka、RabbitMQ 等消息中间件用户态或通过 java.nio.channels.Pipe 实现线程间通信不是进程间4.共享内存将同一块物理内存映射到多个进程的虚拟地址空间中一个进程修改后另一个进程直接可见。优点速度最快没有内核介入的数据拷贝只需一次页表映射。难点需要同步机制比如信号量来避免竞争条件。Java 实现方式包括使用 MappedByteBuffer FileChannel 映射文件到内存不同进程映射同一个文件类似 mmap。使用第三方库如 Chronicle Map或 JNI 调用 POSIX 的 shmget / shmat。// Java 中使用内存映射文件模拟共享内存RandomAccessFilefilenewRandomAccessFile(shared.dat,rw);FileChannelchannelfile.getChannel();MappedByteBufferbufferchannel.map(FileChannel.MapMode.READ_WRITE,0,1024);// 进程 A 写入buffer.putInt(0,100);// 进程 B 读取intvaluebuffer.getInt(0);5.信号量一个整数计数器支持 P等待和 V释放操作用于控制多进程对共享资源的访问。与互斥锁的区别信号量可以允许多个线程同时访问计数型互斥锁只允许一个。Java 中的相关类java.util.concurrent.Semaphore 用于线程间不直接用于进程间。若需进程间信号量需使用 FileLock 或 JNI 调用系统信号量。6.信号Signal软件中断异步通知进程某个事件发生。常见信号SIGKILL强制终止、SIGTERM请求终止、SIGINTCtrlC。特点携带信息少只用来通知事件不传递数据。Java 中的处理通过 Runtime.getRuntime().addShutdownHook 捕获 SIGTERM 等信号更细粒度的信号处理可以使用 sun.misc.Signal非标准或 jdk.internal.misc.Signal。// 优雅关闭示例Runtime.getRuntime().addShutdownHook(newThread(()-{System.out.println(收到终止信号正在释放资源...);}));7.Socket通过网络协议栈TCP/UDP通信可以跨主机。本地进程间通信可使用 Unix Domain Socket比 TCP 更快不走网络协议栈。优点通用性强支持跨网络、跨语言。Java 中的优势java.net.Socket / ServerSocket 以及 NIO 提供了非常成熟的实现。本地通信可指定 localhost 127.0.0.1。// 服务端ServerSocketservernewServerSocket(8888);Socketclientserver.accept();// 客户端SocketsocketnewSocket(localhost,8888);面试问题1.共享内存为什么最快其他IPC方式管道、消息队列、Socket通常需要将数据从用户空间拷贝到内核空间再拷贝到接收方用户空间共两次拷贝。而共享内存只在内核中建立映射进程直接读写同一块物理内存无需拷贝。2.Java 中为什么很少直接用共享内存Java 的内存模型屏蔽了物理内存的直接操作跨 JVM 的共享内存需要依赖 MappedByteBuffer 或 JNI且需要自行处理内存布局、字节序、同步等问题复杂度高。通常使用 Redis、Kafka 等中间件来代替。3.管道和消息队列的核心区别管道是无格式的字节流没有消息边界消息队列是有格式的独立消息每个消息有类型和长度接收方可以按类型读取。4.信号量和互斥锁的区别互斥锁是二元信号量0/1用于保护临界区信号量可以大于1允许多个资源实例被并发访问。另外互斥锁要求同一个线程释放信号量可以由不同进程释放。

更多文章