Loading

[操作系统]进程通信

管道,消息队列,信号量,socket,共享内存

管道

在 Java 中,可以使用管道通过进程间通信。以下是一个简单的例子,展示了如何通过 ProcessBuilder 创建两个进程,并使用输入和输出流进行通信。

示例代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class ProcessCommunication {
    public static void main(String[] args) {
        try {
            // 创建子进程
            ProcessBuilder builder = new ProcessBuilder("java", "ChildProcess");
            Process process = builder.start();

            // 向子进程写数据
            try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream()), true)) {
                writer.println("Hello from parent process!");
            }

            // 从子进程读取数据
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println("Received from child process: " + line);
                }
            }

            process.waitFor();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

// 子进程类
class ChildProcess {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
             PrintWriter writer = new PrintWriter(new OutputStreamWriter(System.out), true)) {

            // 从父进程读取数据
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("Received from parent process: " + line);

                // 向父进程发送响应
                writer.println("Hello from child process!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

说明

  1. 父进程:

    • 使用 ProcessBuilder 启动子进程。
    • 通过 OutputStreamWriter 向子进程发送数据。
    • 通过 InputStreamReader 接收子进程的数据。
  2. 子进程:

    • 使用 System.in 读取父进程发送的数据。
    • 使用 System.out 发送响应回父进程。

注意事项

  • 确保 ChildProcess 类在同一个项目中可以被找到和执行。
  • 管道通信适合简单数据交换,复杂通信可以考虑使用其他机制如 sockets 或消息队列。

消息队列

在 Java 中,使用消息队列进行进程间通信可以通过 Java Message Service (JMS) 实现。以下是一个简单的例子,展示了如何使用 ActiveMQ 作为消息队列。

环境设置

  1. 下载并安装 ActiveMQ:确保 ActiveMQ 正在运行。

  2. 添加依赖:如果使用 Maven,添加 ActiveMQ 的依赖。

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-all</artifactId>
    <version>5.16.3</version>
</dependency>

示例代码

消息生产者

import javax.jms.;
import org.apache.activemq.ActiveMQConnectionFactory;

public class MessageProducerExample {
    public static void main(String[] args) {
        ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
        
        try (Connection connection = factory.createConnection();
             Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {

            Queue queue = session.createQueue("exampleQueue");

            javax.jms.MessageProducer producer = session.createProducer(queue);
            TextMessage message = session.createTextMessage("Hello from producer!");

            producer.send(message);
            System.out.println("Message sent: " + message.getText());
            
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

消息消费者

import javax.jms.;
import org.apache.activemq.ActiveMQConnectionFactory;

public class MessageConsumerExample {
    public static void main(String[] args) {
        ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
        
        try (Connection connection = factory.createConnection();
             Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {

            Queue queue = session.createQueue("exampleQueue");
            javax.jms.MessageConsumer consumer = session.createConsumer(queue);

            connection.start();

            Message message = consumer.receive();
            if (message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                System.out.println("Received message: " + textMessage.getText());
            }
            
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

说明

  • ActiveMQConnectionFactory: 用于连接到 ActiveMQ 服务器。
  • Session: 用于创建生产者、消费者和消息。
  • Queue: 消息队列的名字,生产者和消费者使用相同的队列名进行通信。
  • TextMessage: 用于发送和接收文本消息。

注意事项

  • 确保 ActiveMQ 服务器正在运行,并在正确的端口上监听。
  • 代码中的连接 URL (tcp://localhost:61616) 可能需要根据实际情况调整。
  • 生产者和消费者可以在不同的进程中运行,甚至可以在不同的机器上,只要它们能够访问同一个 ActiveMQ 服务器。

信号量

在 Java 中,信号量通常用于线程间的同步,而不是进程间通信。进程间通信通常通过其他机制实现,如消息队列、管道、套接字等。不过,你可以使用共享文件或数据库结合信号量来模拟进程间通信。

下面是使用信号量进行线程间同步的示例:

示例代码

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    private static final Semaphore semaphore = new Semaphore(1);

    public static void main(String[] args) {
        Thread t1 = new Thread(new Worker("Thread 1"));
        Thread t2 = new Thread(new Worker("Thread 2"));

        t1.start();
        t2.start();
    }

    static class Worker implements Runnable {
        private final String name;

        Worker(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            try {
                System.out.println(name + " is waiting for a permit.");
                semaphore.acquire();
                System.out.println(name + " acquired a permit.");

                // 模拟工作
                Thread.sleep(2000);

                System.out.println(name + " releasing permit.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
        }
    }
}

说明

  • Semaphore: 控制对共享资源的访问。new Semaphore(1) 创建一个只有一个许可的信号量,类似于互斥锁。
  • acquire(): 获取许可,如果没有可用的许可,线程将会被阻塞。
  • release(): 释放许可,唤醒等待的线程。

进程间通信

如果你需要进程间通信,可以考虑使用以下机制:

  • 文件:进程通过读写共享文件进行通信。
  • 数据库:进程通过读写共享数据库记录进行通信。
  • Sockets:使用网络套接字进行通信。
  • 消息队列:如 JMS。

信号量本身在 Java 中不直接用于进程间通信,但可以作为同步机制与其他方法结合使用。

posted @   Duancf  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示